e23c30789a6601acf24fae3101dc0647e6fb4c21
[ira/wip.git] / source / param / loadparm.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Parameter loading functions
4    Copyright (C) Karl Auer 1993-1998
5
6    Largely re-written by Andrew Tridgell, September 1994
7
8    Copyright (C) Simo Sorce 2001
9    Copyright (C) Alexander Bokovoy 2002
10    Copyright (C) Stefan (metze) Metzmacher 2002
11    Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2003
12    Copyright (C) Michael Adam 2008
13    
14    This program is free software; you can redistribute it and/or modify
15    it under the terms of the GNU General Public License as published by
16    the Free Software Foundation; either version 3 of the License, or
17    (at your option) any later version.
18    
19    This program is distributed in the hope that it will be useful,
20    but WITHOUT ANY WARRANTY; without even the implied warranty of
21    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22    GNU General Public License for more details.
23    
24    You should have received a copy of the GNU General Public License
25    along with this program.  If not, see <http://www.gnu.org/licenses/>.
26 */
27
28 /*
29  *  Load parameters.
30  *
31  *  This module provides suitable callback functions for the params
32  *  module. It builds the internal table of service details which is
33  *  then used by the rest of the server.
34  *
35  * To add a parameter:
36  *
37  * 1) add it to the global or service structure definition
38  * 2) add it to the parm_table
39  * 3) add it to the list of available functions (eg: using FN_GLOBAL_STRING())
40  * 4) If it's a global then initialise it in init_globals. If a local
41  *    (ie. service) parameter then initialise it in the sDefault structure
42  *  
43  *
44  * Notes:
45  *   The configuration file is processed sequentially for speed. It is NOT
46  *   accessed randomly as happens in 'real' Windows. For this reason, there
47  *   is a fair bit of sequence-dependent code here - ie., code which assumes
48  *   that certain things happen before others. In particular, the code which
49  *   happens at the boundary between sections is delicately poised, so be
50  *   careful!
51  *
52  */
53
54 #include "includes.h"
55 #include "libnet/libnet.h"
56
57 bool in_client = False;         /* Not in the client by default */
58 bool bLoaded = False;
59
60 extern enum protocol_types Protocol;
61 extern userdom_struct current_user_info;
62
63 #ifndef GLOBAL_NAME
64 #define GLOBAL_NAME "global"
65 #endif
66
67 #ifndef PRINTERS_NAME
68 #define PRINTERS_NAME "printers"
69 #endif
70
71 #ifndef HOMES_NAME
72 #define HOMES_NAME "homes"
73 #endif
74
75 static uint64_t conf_last_seqnum = 0;
76 static struct libnet_conf_ctx *conf_ctx = NULL;
77
78 #define CONFIG_BACKEND_FILE 0
79 #define CONFIG_BACKEND_REGISTRY 1
80
81 static int config_backend = CONFIG_BACKEND_FILE;
82
83 /* some helpful bits */
84 #define LP_SNUM_OK(i) (((i) >= 0) && ((i) < iNumServices) && (ServicePtrs != NULL) && ServicePtrs[(i)]->valid)
85 #define VALID(i) (ServicePtrs != NULL && ServicePtrs[i]->valid)
86
87 #define USERSHARE_VALID 1
88 #define USERSHARE_PENDING_DELETE 2
89
90 extern int extra_time_offset;
91
92 static bool defaults_saved = False;
93
94 typedef struct _param_opt_struct param_opt_struct;
95 struct _param_opt_struct {
96         param_opt_struct *prev, *next;
97         char *key;
98         char *value;
99         char **list;
100 };
101
102 /* 
103  * This structure describes global (ie., server-wide) parameters.
104  */
105 typedef struct {
106         int ConfigBackend;
107         char *smb_ports;
108         char *dos_charset;
109         char *unix_charset;
110         char *display_charset;
111         char *szPrintcapname;
112         char *szAddPortCommand;
113         char *szEnumPortsCommand;
114         char *szAddPrinterCommand;
115         char *szDeletePrinterCommand;
116         char *szOs2DriverMap;
117         char *szLockDir;
118         char *szPidDir;
119         char *szRootdir;
120         char *szDefaultService;
121         char *szGetQuota;
122         char *szSetQuota;
123         char *szMsgCommand;
124         char *szServerString;
125         char *szAutoServices;
126         char *szPasswdProgram;
127         char *szPasswdChat;
128         char *szLogFile;
129         char *szConfigFile;
130         char *szSMBPasswdFile;
131         char *szPrivateDir;
132         char *szPassdbBackend;
133         char **szPreloadModules;
134         char *szPasswordServer;
135         char *szSocketOptions;
136         char *szRealm;
137         char *szAfsUsernameMap;
138         int iAfsTokenLifetime;
139         char *szLogNtTokenCommand;
140         char *szUsernameMap;
141         char *szLogonScript;
142         char *szLogonPath;
143         char *szLogonDrive;
144         char *szLogonHome;
145         char **szWINSservers;
146         char **szInterfaces;
147         char *szRemoteAnnounce;
148         char *szRemoteBrowseSync;
149         char *szSocketAddress;
150         char *szNISHomeMapName;
151         char *szAnnounceVersion;        /* This is initialised in init_globals */
152         char *szWorkgroup;
153         char *szNetbiosName;
154         char **szNetbiosAliases;
155         char *szNetbiosScope;
156         char *szNameResolveOrder;
157         char *szPanicAction;
158         char *szAddUserScript;
159         char *szRenameUserScript;
160         char *szDelUserScript;
161         char *szAddGroupScript;
162         char *szDelGroupScript;
163         char *szAddUserToGroupScript;
164         char *szDelUserFromGroupScript;
165         char *szSetPrimaryGroupScript;
166         char *szAddMachineScript;
167         char *szShutdownScript;
168         char *szAbortShutdownScript;
169         char *szUsernameMapScript;
170         char *szCheckPasswordScript;
171         char *szWINSHook;
172         char *szUtmpDir;
173         char *szWtmpDir;
174         bool bUtmp;
175         char *szIdmapUID;
176         char *szIdmapGID;
177         bool bPassdbExpandExplicit;
178         int AlgorithmicRidBase;
179         char *szTemplateHomedir;
180         char *szTemplateShell;
181         char *szWinbindSeparator;
182         bool bWinbindEnumUsers;
183         bool bWinbindEnumGroups;
184         bool bWinbindUseDefaultDomain;
185         bool bWinbindTrustedDomainsOnly;
186         bool bWinbindNestedGroups;
187         int  winbind_expand_groups;
188         bool bWinbindRefreshTickets;
189         bool bWinbindOfflineLogon;
190         bool bWinbindNormalizeNames;
191         bool bWinbindRpcOnly;
192         char **szIdmapDomains;
193         char **szIdmapBackend; /* deprecated */
194         char *szIdmapAllocBackend;
195         char *szAddShareCommand;
196         char *szChangeShareCommand;
197         char *szDeleteShareCommand;
198         char **szEventLogs;
199         char *szGuestaccount;
200         char *szManglingMethod;
201         char **szServicesList;
202         char *szUsersharePath;
203         char *szUsershareTemplateShare;
204         char **szUsersharePrefixAllowList;
205         char **szUsersharePrefixDenyList;
206         int mangle_prefix;
207         int max_log_size;
208         char *szLogLevel;
209         int max_xmit;
210         int max_mux;
211         int max_open_files;
212         int open_files_db_hash_size;
213         int pwordlevel;
214         int unamelevel;
215         int deadtime;
216         bool getwd_cache;
217         int maxprotocol;
218         int minprotocol;
219         int security;
220         char **AuthMethods;
221         bool paranoid_server_security;
222         int maxdisksize;
223         int lpqcachetime;
224         int iMaxSmbdProcesses;
225         bool bDisableSpoolss;
226         int syslog;
227         int os_level;
228         bool enhanced_browsing;
229         int max_ttl;
230         int max_wins_ttl;
231         int min_wins_ttl;
232         int lm_announce;
233         int lm_interval;
234         int announce_as;        /* This is initialised in init_globals */
235         int machine_password_timeout;
236         int map_to_guest;
237         int oplock_break_wait_time;
238         int winbind_cache_time;
239         int winbind_max_idle_children;
240         char **szWinbindNssInfo;
241         int iLockSpinTime;
242         char *szLdapMachineSuffix;
243         char *szLdapUserSuffix;
244         char *szLdapIdmapSuffix;
245         char *szLdapGroupSuffix;
246         int ldap_ssl;
247         char *szLdapSuffix;
248         char *szLdapAdminDn;
249         int ldap_debug_level;
250         int ldap_debug_threshold;
251         int iAclCompat;
252         char *szCupsServer;
253         char *szIPrintServer;
254         char *ctdbdSocket;
255         char **szClusterAddresses;
256         bool clustering;
257         int ldap_passwd_sync;
258         int ldap_replication_sleep;
259         int ldap_timeout; /* This is initialised in init_globals */
260         int ldap_page_size;
261         bool ldap_delete_dn;
262         bool bMsAddPrinterWizard;
263         bool bDNSproxy;
264         bool bWINSsupport;
265         bool bWINSproxy;
266         bool bLocalMaster;
267         int  iPreferredMaster;
268         int iDomainMaster;
269         bool bDomainLogons;
270         bool bEncryptPasswords;
271         bool bUpdateEncrypt;
272         int  clientSchannel;
273         int  serverSchannel;
274         bool bNullPasswords;
275         bool bObeyPamRestrictions;
276         bool bLoadPrinters;
277         int PrintcapCacheTime;
278         bool bLargeReadwrite;
279         bool bReadRaw;
280         bool bWriteRaw;
281         bool bSyslogOnly;
282         bool bBrowseList;
283         bool bNISHomeMap;
284         bool bTimeServer;
285         bool bBindInterfacesOnly;
286         bool bPamPasswordChange;
287         bool bUnixPasswdSync;
288         bool bPasswdChatDebug;
289         int iPasswdChatTimeout;
290         bool bTimestampLogs;
291         bool bNTSmbSupport;
292         bool bNTPipeSupport;
293         bool bNTStatusSupport;
294         bool bStatCache;
295         int iMaxStatCacheSize;
296         bool bKernelOplocks;
297         bool bAllowTrustedDomains;
298         bool bLanmanAuth;
299         bool bNTLMAuth;
300         bool bUseSpnego;
301         bool bClientLanManAuth;
302         bool bClientNTLMv2Auth;
303         bool bClientPlaintextAuth;
304         bool bClientUseSpnego;
305         bool bDebugPrefixTimestamp;
306         bool bDebugHiresTimestamp;
307         bool bDebugPid;
308         bool bDebugUid;
309         bool bDebugClass;
310         bool bEnableCoreFiles;
311         bool bHostMSDfs;
312         bool bUseMmap;
313         bool bHostnameLookups;
314         bool bUnixExtensions;
315         bool bDisableNetbios;
316         bool bUseKerberosKeytab;
317         bool bDeferSharingViolations;
318         bool bEnablePrivileges;
319         bool bASUSupport;
320         bool bUsershareOwnerOnly;
321         bool bUsershareAllowGuests;
322         bool bRegistryShares;
323         int restrict_anonymous;
324         int name_cache_timeout;
325         int client_signing;
326         int server_signing;
327         int client_ldap_sasl_wrapping;
328         int iUsershareMaxShares;
329         int iIdmapCacheTime;
330         int iIdmapNegativeCacheTime;
331
332         bool bResetOnZeroVC;
333         int iKeepalive;
334         int iminreceivefile;
335         param_opt_struct *param_opt;
336 } global;
337
338 static global Globals;
339
340 /* 
341  * This structure describes a single service. 
342  */
343 typedef struct {
344         bool valid;
345         bool autoloaded;
346         int usershare;
347         time_t usershare_last_mod;
348         char *szService;
349         char *szPath;
350         char *szUsername;
351         char **szInvalidUsers;
352         char **szValidUsers;
353         char **szAdminUsers;
354         char *szCopy;
355         char *szInclude;
356         char *szPreExec;
357         char *szPostExec;
358         char *szRootPreExec;
359         char *szRootPostExec;
360         char *szCupsOptions;
361         char *szPrintcommand;
362         char *szLpqcommand;
363         char *szLprmcommand;
364         char *szLppausecommand;
365         char *szLpresumecommand;
366         char *szQueuepausecommand;
367         char *szQueueresumecommand;
368         char *szPrintername;
369         char *szPrintjobUsername;
370         char *szDontdescend;
371         char **szHostsallow;
372         char **szHostsdeny;
373         char *szMagicScript;
374         char *szMagicOutput;
375         char *szVetoFiles;
376         char *szHideFiles;
377         char *szVetoOplockFiles;
378         char *comment;
379         char *force_user;
380         char *force_group;
381         char **readlist;
382         char **writelist;
383         char **printer_admin;
384         char *volume;
385         char *fstype;
386         char **szVfsObjects;
387         char *szMSDfsProxy;
388         char *szAioWriteBehind;
389         char *szDfree;
390         int iMinPrintSpace;
391         int iMaxPrintJobs;
392         int iMaxReportedPrintJobs;
393         int iWriteCacheSize;
394         int iCreate_mask;
395         int iCreate_force_mode;
396         int iSecurity_mask;
397         int iSecurity_force_mode;
398         int iDir_mask;
399         int iDir_force_mode;
400         int iDir_Security_mask;
401         int iDir_Security_force_mode;
402         int iMaxConnections;
403         int iDefaultCase;
404         int iPrinting;
405         int iOplockContentionLimit;
406         int iCSCPolicy;
407         int iBlock_size;
408         int iDfreeCacheTime;
409         bool bPreexecClose;
410         bool bRootpreexecClose;
411         int  iCaseSensitive;
412         bool bCasePreserve;
413         bool bShortCasePreserve;
414         bool bHideDotFiles;
415         bool bHideSpecialFiles;
416         bool bHideUnReadable;
417         bool bHideUnWriteableFiles;
418         bool bBrowseable;
419         bool bAvailable;
420         bool bRead_only;
421         bool bNo_set_dir;
422         bool bGuest_only;
423         bool bHidden;
424         bool bGuest_ok;
425         bool bPrint_ok;
426         bool bMap_system;
427         bool bMap_hidden;
428         bool bMap_archive;
429         bool bStoreDosAttributes;
430         bool bDmapiSupport;
431         bool bLocking;
432         int iStrictLocking;
433         bool bPosixLocking;
434         bool bShareModes;
435         bool bOpLocks;
436         bool bLevel2OpLocks;
437         bool bOnlyUser;
438         bool bMangledNames;
439         bool bWidelinks;
440         bool bSymlinks;
441         bool bSyncAlways;
442         bool bStrictAllocate;
443         bool bStrictSync;
444         char magic_char;
445         struct bitmap *copymap;
446         bool bDeleteReadonly;
447         bool bFakeOplocks;
448         bool bDeleteVetoFiles;
449         bool bDosFilemode;
450         bool bDosFiletimes;
451         bool bDosFiletimeResolution;
452         bool bFakeDirCreateTimes;
453         bool bBlockingLocks;
454         bool bInheritPerms;
455         bool bInheritACLS;
456         bool bInheritOwner;
457         bool bMSDfsRoot;
458         bool bUseClientDriver;
459         bool bDefaultDevmode;
460         bool bForcePrintername;
461         bool bNTAclSupport;
462         bool bForceUnknownAclUser;
463         bool bUseSendfile;
464         bool bProfileAcls;
465         bool bMap_acl_inherit;
466         bool bAfs_Share;
467         bool bEASupport;
468         bool bAclCheckPermissions;
469         bool bAclMapFullControl;
470         bool bAclGroupControl;
471         bool bChangeNotify;
472         bool bKernelChangeNotify;
473         int iallocation_roundup_size;
474         int iAioReadSize;
475         int iAioWriteSize;
476         int iMap_readonly;
477         int iDirectoryNameCacheSize;
478         int ismb_encrypt;
479         param_opt_struct *param_opt;
480
481         char dummy[3];          /* for alignment */
482 } service;
483
484
485 /* This is a default service used to prime a services structure */
486 static service sDefault = {
487         True,                   /* valid */
488         False,                  /* not autoloaded */
489         0,                      /* not a usershare */
490         (time_t)0,              /* No last mod time */
491         NULL,                   /* szService */
492         NULL,                   /* szPath */
493         NULL,                   /* szUsername */
494         NULL,                   /* szInvalidUsers */
495         NULL,                   /* szValidUsers */
496         NULL,                   /* szAdminUsers */
497         NULL,                   /* szCopy */
498         NULL,                   /* szInclude */
499         NULL,                   /* szPreExec */
500         NULL,                   /* szPostExec */
501         NULL,                   /* szRootPreExec */
502         NULL,                   /* szRootPostExec */
503         NULL,                   /* szCupsOptions */
504         NULL,                   /* szPrintcommand */
505         NULL,                   /* szLpqcommand */
506         NULL,                   /* szLprmcommand */
507         NULL,                   /* szLppausecommand */
508         NULL,                   /* szLpresumecommand */
509         NULL,                   /* szQueuepausecommand */
510         NULL,                   /* szQueueresumecommand */
511         NULL,                   /* szPrintername */
512         NULL,                   /* szPrintjobUsername */
513         NULL,                   /* szDontdescend */
514         NULL,                   /* szHostsallow */
515         NULL,                   /* szHostsdeny */
516         NULL,                   /* szMagicScript */
517         NULL,                   /* szMagicOutput */
518         NULL,                   /* szVetoFiles */
519         NULL,                   /* szHideFiles */
520         NULL,                   /* szVetoOplockFiles */
521         NULL,                   /* comment */
522         NULL,                   /* force user */
523         NULL,                   /* force group */
524         NULL,                   /* readlist */
525         NULL,                   /* writelist */
526         NULL,                   /* printer admin */
527         NULL,                   /* volume */
528         NULL,                   /* fstype */
529         NULL,                   /* vfs objects */
530         NULL,                   /* szMSDfsProxy */
531         NULL,                   /* szAioWriteBehind */
532         NULL,                   /* szDfree */
533         0,                      /* iMinPrintSpace */
534         1000,                   /* iMaxPrintJobs */
535         0,                      /* iMaxReportedPrintJobs */
536         0,                      /* iWriteCacheSize */
537         0744,                   /* iCreate_mask */
538         0000,                   /* iCreate_force_mode */
539         0777,                   /* iSecurity_mask */
540         0,                      /* iSecurity_force_mode */
541         0755,                   /* iDir_mask */
542         0000,                   /* iDir_force_mode */
543         0777,                   /* iDir_Security_mask */
544         0,                      /* iDir_Security_force_mode */
545         0,                      /* iMaxConnections */
546         CASE_LOWER,             /* iDefaultCase */
547         DEFAULT_PRINTING,       /* iPrinting */
548         2,                      /* iOplockContentionLimit */
549         0,                      /* iCSCPolicy */
550         1024,                   /* iBlock_size */
551         0,                      /* iDfreeCacheTime */
552         False,                  /* bPreexecClose */
553         False,                  /* bRootpreexecClose */
554         Auto,                   /* case sensitive */
555         True,                   /* case preserve */
556         True,                   /* short case preserve */
557         True,                   /* bHideDotFiles */
558         False,                  /* bHideSpecialFiles */
559         False,                  /* bHideUnReadable */
560         False,                  /* bHideUnWriteableFiles */
561         True,                   /* bBrowseable */
562         True,                   /* bAvailable */
563         True,                   /* bRead_only */
564         True,                   /* bNo_set_dir */
565         False,                  /* bGuest_only */
566         False,                  /* bHidden */
567         False,                  /* bGuest_ok */
568         False,                  /* bPrint_ok */
569         False,                  /* bMap_system */
570         False,                  /* bMap_hidden */
571         True,                   /* bMap_archive */
572         False,                  /* bStoreDosAttributes */
573         False,                  /* bDmapiSupport */
574         True,                   /* bLocking */
575         Auto,                   /* iStrictLocking */
576         True,                   /* bPosixLocking */
577         True,                   /* bShareModes */
578         True,                   /* bOpLocks */
579         True,                   /* bLevel2OpLocks */
580         False,                  /* bOnlyUser */
581         True,                   /* bMangledNames */
582         True,                   /* bWidelinks */
583         True,                   /* bSymlinks */
584         False,                  /* bSyncAlways */
585         False,                  /* bStrictAllocate */
586         False,                  /* bStrictSync */
587         '~',                    /* magic char */
588         NULL,                   /* copymap */
589         False,                  /* bDeleteReadonly */
590         False,                  /* bFakeOplocks */
591         False,                  /* bDeleteVetoFiles */
592         False,                  /* bDosFilemode */
593         True,                   /* bDosFiletimes */
594         False,                  /* bDosFiletimeResolution */
595         False,                  /* bFakeDirCreateTimes */
596         True,                   /* bBlockingLocks */
597         False,                  /* bInheritPerms */
598         False,                  /* bInheritACLS */
599         False,                  /* bInheritOwner */
600         False,                  /* bMSDfsRoot */
601         False,                  /* bUseClientDriver */
602         True,                   /* bDefaultDevmode */
603         False,                  /* bForcePrintername */
604         True,                   /* bNTAclSupport */
605         False,                  /* bForceUnknownAclUser */
606         False,                  /* bUseSendfile */
607         False,                  /* bProfileAcls */
608         False,                  /* bMap_acl_inherit */
609         False,                  /* bAfs_Share */
610         False,                  /* bEASupport */
611         True,                   /* bAclCheckPermissions */
612         True,                   /* bAclMapFullControl */
613         False,                  /* bAclGroupControl */
614         True,                   /* bChangeNotify */
615         True,                   /* bKernelChangeNotify */
616         SMB_ROUNDUP_ALLOCATION_SIZE,            /* iallocation_roundup_size */
617         0,                      /* iAioReadSize */
618         0,                      /* iAioWriteSize */
619         MAP_READONLY_YES,       /* iMap_readonly */
620 #ifdef BROKEN_DIRECTORY_HANDLING
621         0,                      /* iDirectoryNameCacheSize */
622 #else
623         100,                    /* iDirectoryNameCacheSize */
624 #endif
625         Auto,                   /* ismb_encrypt */
626         NULL,                   /* Parametric options */
627
628         ""                      /* dummy */
629 };
630
631 /* local variables */
632 static service **ServicePtrs = NULL;
633 static int iNumServices = 0;
634 static int iServiceIndex = 0;
635 static struct db_context *ServiceHash;
636 static int *invalid_services = NULL;
637 static int num_invalid_services = 0;
638 static bool bInGlobalSection = True;
639 static bool bGlobalOnly = False;
640 static int server_role;
641 static int default_server_announce;
642
643 #define NUMPARAMETERS (sizeof(parm_table) / sizeof(struct parm_struct))
644
645 /* prototypes for the special type handlers */
646 static bool handle_include( int snum, const char *pszParmValue, char **ptr);
647 static bool handle_copy( int snum, const char *pszParmValue, char **ptr);
648 static bool handle_netbios_name( int snum, const char *pszParmValue, char **ptr);
649 static bool handle_idmap_uid( int snum, const char *pszParmValue, char **ptr);
650 static bool handle_idmap_gid( int snum, const char *pszParmValue, char **ptr);
651 static bool handle_debug_list( int snum, const char *pszParmValue, char **ptr );
652 static bool handle_workgroup( int snum, const char *pszParmValue, char **ptr );
653 static bool handle_netbios_aliases( int snum, const char *pszParmValue, char **ptr );
654 static bool handle_netbios_scope( int snum, const char *pszParmValue, char **ptr );
655 static bool handle_charset( int snum, const char *pszParmValue, char **ptr );
656 static bool handle_printing( int snum, const char *pszParmValue, char **ptr);
657 static bool handle_ldap_debug_level( int snum, const char *pszParmValue, char **ptr);
658
659 static void set_server_role(void);
660 static void set_default_server_announce_type(void);
661 static void set_allowed_client_auth(void);
662
663 static const struct enum_list enum_protocol[] = {
664         {PROTOCOL_NT1, "NT1"},
665         {PROTOCOL_LANMAN2, "LANMAN2"},
666         {PROTOCOL_LANMAN1, "LANMAN1"},
667         {PROTOCOL_CORE, "CORE"},
668         {PROTOCOL_COREPLUS, "COREPLUS"},
669         {PROTOCOL_COREPLUS, "CORE+"},
670         {-1, NULL}
671 };
672
673 static const struct enum_list enum_security[] = {
674         {SEC_SHARE, "SHARE"},
675         {SEC_USER, "USER"},
676         {SEC_SERVER, "SERVER"},
677         {SEC_DOMAIN, "DOMAIN"},
678 #ifdef HAVE_ADS
679         {SEC_ADS, "ADS"},
680 #endif
681         {-1, NULL}
682 };
683
684 static const struct enum_list enum_printing[] = {
685         {PRINT_SYSV, "sysv"},
686         {PRINT_AIX, "aix"},
687         {PRINT_HPUX, "hpux"},
688         {PRINT_BSD, "bsd"},
689         {PRINT_QNX, "qnx"},
690         {PRINT_PLP, "plp"},
691         {PRINT_LPRNG, "lprng"},
692         {PRINT_CUPS, "cups"},
693         {PRINT_IPRINT, "iprint"},
694         {PRINT_LPRNT, "nt"},
695         {PRINT_LPROS2, "os2"},
696 #ifdef DEVELOPER
697         {PRINT_TEST, "test"},
698         {PRINT_VLP, "vlp"},
699 #endif /* DEVELOPER */
700         {-1, NULL}
701 };
702
703 static const struct enum_list enum_ldap_sasl_wrapping[] = {
704         {0, "plain"},
705         {ADS_AUTH_SASL_SIGN, "sign"},
706         {ADS_AUTH_SASL_SEAL, "seal"},
707         {-1, NULL}
708 };
709
710 static const struct enum_list enum_ldap_ssl[] = {
711         {LDAP_SSL_OFF, "no"},
712         {LDAP_SSL_OFF, "No"},
713         {LDAP_SSL_OFF, "off"},
714         {LDAP_SSL_OFF, "Off"},
715         {LDAP_SSL_START_TLS, "start tls"},
716         {LDAP_SSL_START_TLS, "Start_tls"},
717         {-1, NULL}
718 };
719
720 static const struct enum_list enum_ldap_passwd_sync[] = {
721         {LDAP_PASSWD_SYNC_OFF, "no"},
722         {LDAP_PASSWD_SYNC_OFF, "No"},
723         {LDAP_PASSWD_SYNC_OFF, "off"},
724         {LDAP_PASSWD_SYNC_OFF, "Off"},
725         {LDAP_PASSWD_SYNC_ON, "Yes"},
726         {LDAP_PASSWD_SYNC_ON, "yes"},
727         {LDAP_PASSWD_SYNC_ON, "on"},
728         {LDAP_PASSWD_SYNC_ON, "On"},
729         {LDAP_PASSWD_SYNC_ONLY, "Only"},
730         {LDAP_PASSWD_SYNC_ONLY, "only"},
731         {-1, NULL}
732 };
733
734 /* Types of machine we can announce as. */
735 #define ANNOUNCE_AS_NT_SERVER 1
736 #define ANNOUNCE_AS_WIN95 2
737 #define ANNOUNCE_AS_WFW 3
738 #define ANNOUNCE_AS_NT_WORKSTATION 4
739
740 static const struct enum_list enum_announce_as[] = {
741         {ANNOUNCE_AS_NT_SERVER, "NT"},
742         {ANNOUNCE_AS_NT_SERVER, "NT Server"},
743         {ANNOUNCE_AS_NT_WORKSTATION, "NT Workstation"},
744         {ANNOUNCE_AS_WIN95, "win95"},
745         {ANNOUNCE_AS_WFW, "WfW"},
746         {-1, NULL}
747 };
748
749 static const struct enum_list enum_map_readonly[] = {
750         {MAP_READONLY_NO, "no"},
751         {MAP_READONLY_NO, "false"},
752         {MAP_READONLY_NO, "0"},
753         {MAP_READONLY_YES, "yes"},
754         {MAP_READONLY_YES, "true"},
755         {MAP_READONLY_YES, "1"},
756         {MAP_READONLY_PERMISSIONS, "permissions"},
757         {MAP_READONLY_PERMISSIONS, "perms"},
758         {-1, NULL}
759 };
760
761 static const struct enum_list enum_case[] = {
762         {CASE_LOWER, "lower"},
763         {CASE_UPPER, "upper"},
764         {-1, NULL}
765 };
766
767 static const struct enum_list enum_bool_auto[] = {
768         {False, "No"},
769         {False, "False"},
770         {False, "0"},
771         {True, "Yes"},
772         {True, "True"},
773         {True, "1"},
774         {Auto, "Auto"},
775         {-1, NULL}
776 };
777
778 /* Client-side offline caching policy types */
779 #define CSC_POLICY_MANUAL 0
780 #define CSC_POLICY_DOCUMENTS 1
781 #define CSC_POLICY_PROGRAMS 2
782 #define CSC_POLICY_DISABLE 3
783
784 static const struct enum_list enum_csc_policy[] = {
785         {CSC_POLICY_MANUAL, "manual"},
786         {CSC_POLICY_DOCUMENTS, "documents"},
787         {CSC_POLICY_PROGRAMS, "programs"},
788         {CSC_POLICY_DISABLE, "disable"},
789         {-1, NULL}
790 };
791
792 /* SMB signing types. */
793 static const struct enum_list enum_smb_signing_vals[] = {
794         {False, "No"},
795         {False, "False"},
796         {False, "0"},
797         {False, "Off"},
798         {False, "disabled"},
799         {True, "Yes"},
800         {True, "True"},
801         {True, "1"},
802         {True, "On"},
803         {True, "enabled"},
804         {Auto, "auto"},
805         {Required, "required"},
806         {Required, "mandatory"},
807         {Required, "force"},
808         {Required, "forced"},
809         {Required, "enforced"},
810         {-1, NULL}
811 };
812
813 /* ACL compatibility options. */
814 static const struct enum_list enum_acl_compat_vals[] = {
815     { ACL_COMPAT_AUTO, "auto" },
816     { ACL_COMPAT_WINNT, "winnt" },
817     { ACL_COMPAT_WIN2K, "win2k" },
818     { -1, NULL}
819 };
820
821 /* 
822    Do you want session setups at user level security with a invalid
823    password to be rejected or allowed in as guest? WinNT rejects them
824    but it can be a pain as it means "net view" needs to use a password
825
826    You have 3 choices in the setting of map_to_guest:
827
828    "Never" means session setups with an invalid password
829    are rejected. This is the default.
830
831    "Bad User" means session setups with an invalid password
832    are rejected, unless the username does not exist, in which case it
833    is treated as a guest login
834
835    "Bad Password" means session setups with an invalid password
836    are treated as a guest login
837
838    Note that map_to_guest only has an effect in user or server
839    level security.
840 */
841
842 static const struct enum_list enum_map_to_guest[] = {
843         {NEVER_MAP_TO_GUEST, "Never"},
844         {MAP_TO_GUEST_ON_BAD_USER, "Bad User"},
845         {MAP_TO_GUEST_ON_BAD_PASSWORD, "Bad Password"},
846         {MAP_TO_GUEST_ON_BAD_UID, "Bad Uid"},
847         {-1, NULL}
848 };
849
850 /* Config backend options */
851
852 static const struct enum_list enum_config_backend[] = {
853         {CONFIG_BACKEND_FILE, "file"},
854         {CONFIG_BACKEND_REGISTRY, "registry"},
855         {-1, NULL}
856 };
857
858 /* Note: We do not initialise the defaults union - it is not allowed in ANSI C
859  *
860  * The FLAG_HIDE is explicit. Paramters set this way do NOT appear in any edit
861  * screen in SWAT. This is used to exclude parameters as well as to squash all
862  * parameters that have been duplicated by pseudonyms.
863  *
864  * NOTE: To display a parameter in BASIC view set FLAG_BASIC
865  *       Any parameter that does NOT have FLAG_ADVANCED will not disply at all
866  *       Set FLAG_SHARE and FLAG_PRINT to specifically display parameters in
867  *        respective views.
868  *
869  * NOTE2: Handling of duplicated (synonym) paramters:
870  *      Only the first occurance of a parameter should be enabled by FLAG_BASIC
871  *      and/or FLAG_ADVANCED. All duplicates following the first mention should be
872  *      set to FLAG_HIDE. ie: Make you must place the parameter that has the preferred
873  *      name first, and all synonyms must follow it with the FLAG_HIDE attribute.
874  */
875
876 static struct parm_struct parm_table[] = {
877         {N_("Base Options"), P_SEP, P_SEPARATOR}, 
878
879         {"dos charset", P_STRING, P_GLOBAL, &Globals.dos_charset, handle_charset, NULL, FLAG_ADVANCED}, 
880         {"unix charset", P_STRING, P_GLOBAL, &Globals.unix_charset, handle_charset, NULL, FLAG_ADVANCED}, 
881         {"display charset", P_STRING, P_GLOBAL, &Globals.display_charset, handle_charset, NULL, FLAG_ADVANCED}, 
882         {"comment", P_STRING, P_LOCAL, &sDefault.comment, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT}, 
883         {"path", P_STRING, P_LOCAL, &sDefault.szPath, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT}, 
884         {"directory", P_STRING, P_LOCAL, &sDefault.szPath, NULL, NULL, FLAG_HIDE}, 
885         {"workgroup", P_USTRING, P_GLOBAL, &Globals.szWorkgroup, handle_workgroup, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD}, 
886 #ifdef WITH_ADS
887         {"realm", P_USTRING, P_GLOBAL, &Globals.szRealm, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD}, 
888 #endif
889         {"netbios name", P_USTRING, P_GLOBAL, &Globals.szNetbiosName, handle_netbios_name, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD}, 
890         {"netbios aliases", P_LIST, P_GLOBAL, &Globals.szNetbiosAliases, handle_netbios_aliases,  NULL, FLAG_ADVANCED}, 
891         {"netbios scope", P_USTRING, P_GLOBAL, &Globals.szNetbiosScope, handle_netbios_scope,  NULL, FLAG_ADVANCED}, 
892         {"server string", P_STRING, P_GLOBAL, &Globals.szServerString, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED }, 
893         {"interfaces", P_LIST, P_GLOBAL, &Globals.szInterfaces, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD}, 
894         {"bind interfaces only", P_BOOL, P_GLOBAL, &Globals.bBindInterfacesOnly, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD}, 
895
896         {"config backend", P_ENUM, P_GLOBAL, &Globals.ConfigBackend, NULL, enum_config_backend, FLAG_ADVANCED},
897
898         {N_("Security Options"), P_SEP, P_SEPARATOR}, 
899
900         {"security", P_ENUM, P_GLOBAL, &Globals.security, NULL, enum_security, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD}, 
901         {"auth methods", P_LIST, P_GLOBAL, &Globals.AuthMethods, NULL, NULL, FLAG_ADVANCED}, 
902         {"encrypt passwords", P_BOOL, P_GLOBAL, &Globals.bEncryptPasswords, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD}, 
903         {"update encrypted", P_BOOL, P_GLOBAL, &Globals.bUpdateEncrypt, NULL, NULL, FLAG_ADVANCED}, 
904         {"client schannel", P_ENUM, P_GLOBAL, &Globals.clientSchannel, NULL, enum_bool_auto, FLAG_BASIC | FLAG_ADVANCED}, 
905         {"server schannel", P_ENUM, P_GLOBAL, &Globals.serverSchannel, NULL, enum_bool_auto, FLAG_BASIC | FLAG_ADVANCED}, 
906         {"allow trusted domains", P_BOOL, P_GLOBAL, &Globals.bAllowTrustedDomains, NULL, NULL, FLAG_ADVANCED}, 
907         {"map to guest", P_ENUM, P_GLOBAL, &Globals.map_to_guest, NULL, enum_map_to_guest, FLAG_ADVANCED}, 
908         {"null passwords", P_BOOL, P_GLOBAL, &Globals.bNullPasswords, NULL, NULL, FLAG_ADVANCED}, 
909         {"obey pam restrictions", P_BOOL, P_GLOBAL, &Globals.bObeyPamRestrictions, NULL, NULL, FLAG_ADVANCED}, 
910         {"password server", P_STRING, P_GLOBAL, &Globals.szPasswordServer, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD}, 
911         {"smb passwd file", P_STRING, P_GLOBAL, &Globals.szSMBPasswdFile, NULL, NULL, FLAG_ADVANCED}, 
912         {"private dir", P_STRING, P_GLOBAL, &Globals.szPrivateDir, NULL, NULL, FLAG_ADVANCED}, 
913         {"passdb backend", P_STRING, P_GLOBAL, &Globals.szPassdbBackend, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD}, 
914         {"algorithmic rid base", P_INTEGER, P_GLOBAL, &Globals.AlgorithmicRidBase, NULL, NULL, FLAG_ADVANCED}, 
915         {"root directory", P_STRING, P_GLOBAL, &Globals.szRootdir, NULL, NULL, FLAG_ADVANCED}, 
916         {"root dir", P_STRING, P_GLOBAL, &Globals.szRootdir, NULL, NULL, FLAG_HIDE}, 
917         {"root", P_STRING, P_GLOBAL, &Globals.szRootdir, NULL, NULL, FLAG_HIDE}, 
918         {"guest account", P_STRING, P_GLOBAL, &Globals.szGuestaccount, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED}, 
919         {"enable privileges", P_BOOL, P_GLOBAL, &Globals.bEnablePrivileges, NULL, NULL, FLAG_ADVANCED}, 
920
921         {"pam password change", P_BOOL, P_GLOBAL, &Globals.bPamPasswordChange, NULL, NULL, FLAG_ADVANCED}, 
922         {"passwd program", P_STRING, P_GLOBAL, &Globals.szPasswdProgram, NULL, NULL, FLAG_ADVANCED}, 
923         {"passwd chat", P_STRING, P_GLOBAL, &Globals.szPasswdChat, NULL, NULL, FLAG_ADVANCED}, 
924         {"passwd chat debug", P_BOOL, P_GLOBAL, &Globals.bPasswdChatDebug, NULL, NULL, FLAG_ADVANCED}, 
925         {"passwd chat timeout", P_INTEGER, P_GLOBAL, &Globals.iPasswdChatTimeout, NULL, NULL, FLAG_ADVANCED}, 
926         {"check password script", P_STRING, P_GLOBAL, &Globals.szCheckPasswordScript, NULL, NULL, FLAG_ADVANCED}, 
927         {"username map", P_STRING, P_GLOBAL, &Globals.szUsernameMap, NULL, NULL, FLAG_ADVANCED}, 
928         {"password level", P_INTEGER, P_GLOBAL, &Globals.pwordlevel, NULL, NULL, FLAG_ADVANCED}, 
929         {"username level", P_INTEGER, P_GLOBAL, &Globals.unamelevel, NULL, NULL, FLAG_ADVANCED}, 
930         {"unix password sync", P_BOOL, P_GLOBAL, &Globals.bUnixPasswdSync, NULL, NULL, FLAG_ADVANCED}, 
931         {"restrict anonymous", P_INTEGER, P_GLOBAL, &Globals.restrict_anonymous, NULL, NULL, FLAG_ADVANCED}, 
932         {"lanman auth", P_BOOL, P_GLOBAL, &Globals.bLanmanAuth, NULL, NULL, FLAG_ADVANCED}, 
933         {"ntlm auth", P_BOOL, P_GLOBAL, &Globals.bNTLMAuth, NULL, NULL, FLAG_ADVANCED}, 
934         {"client NTLMv2 auth", P_BOOL, P_GLOBAL, &Globals.bClientNTLMv2Auth, NULL, NULL, FLAG_ADVANCED}, 
935         {"client lanman auth", P_BOOL, P_GLOBAL, &Globals.bClientLanManAuth, NULL, NULL, FLAG_ADVANCED}, 
936         {"client plaintext auth", P_BOOL, P_GLOBAL, &Globals.bClientPlaintextAuth, NULL, NULL, FLAG_ADVANCED}, 
937
938         {"username", P_STRING, P_LOCAL, &sDefault.szUsername, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, 
939         {"user", P_STRING, P_LOCAL, &sDefault.szUsername, NULL, NULL, FLAG_HIDE}, 
940         {"users", P_STRING, P_LOCAL, &sDefault.szUsername, NULL, NULL, FLAG_HIDE}, 
941
942         {"invalid users", P_LIST, P_LOCAL, &sDefault.szInvalidUsers, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, 
943         {"valid users", P_LIST, P_LOCAL, &sDefault.szValidUsers, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, 
944         {"admin users", P_LIST, P_LOCAL, &sDefault.szAdminUsers, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, 
945         {"read list", P_LIST, P_LOCAL, &sDefault.readlist, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, 
946         {"write list", P_LIST, P_LOCAL, &sDefault.writelist, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, 
947         {"printer admin", P_LIST, P_LOCAL, &sDefault.printer_admin, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_PRINT | FLAG_DEPRECATED }, 
948         {"force user", P_STRING, P_LOCAL, &sDefault.force_user, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
949         {"force group", P_STRING, P_LOCAL, &sDefault.force_group, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
950         {"group", P_STRING, P_LOCAL, &sDefault.force_group, NULL, NULL, FLAG_ADVANCED}, 
951
952         {"read only", P_BOOL, P_LOCAL, &sDefault.bRead_only, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE}, 
953         {"write ok", P_BOOLREV, P_LOCAL, &sDefault.bRead_only, NULL, NULL, FLAG_HIDE}, 
954         {"writeable", P_BOOLREV, P_LOCAL, &sDefault.bRead_only, NULL, NULL, FLAG_HIDE}, 
955         {"writable", P_BOOLREV, P_LOCAL, &sDefault.bRead_only, NULL, NULL, FLAG_HIDE}, 
956
957         {"acl check permissions", P_BOOL, P_LOCAL, &sDefault.bAclCheckPermissions, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE},
958         {"acl group control", P_BOOL, P_LOCAL, &sDefault.bAclGroupControl, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE | FLAG_DEPRECATED },
959         {"acl map full control", P_BOOL, P_LOCAL, &sDefault.bAclMapFullControl, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE},
960         {"create mask", P_OCTAL, P_LOCAL, &sDefault.iCreate_mask, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, 
961         {"create mode", P_OCTAL, P_LOCAL, &sDefault.iCreate_mask, NULL, NULL, FLAG_HIDE}, 
962         {"force create mode", P_OCTAL, P_LOCAL, &sDefault.iCreate_force_mode, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, 
963         {"security mask", P_OCTAL, P_LOCAL, &sDefault.iSecurity_mask, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, 
964         {"force security mode", P_OCTAL, P_LOCAL, &sDefault.iSecurity_force_mode, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, 
965         {"directory mask", P_OCTAL, P_LOCAL, &sDefault.iDir_mask, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, 
966         {"directory mode", P_OCTAL, P_LOCAL, &sDefault.iDir_mask, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL}, 
967         {"force directory mode", P_OCTAL, P_LOCAL, &sDefault.iDir_force_mode, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, 
968         {"directory security mask", P_OCTAL, P_LOCAL, &sDefault.iDir_Security_mask, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, 
969         {"force directory security mode", P_OCTAL, P_LOCAL, &sDefault.iDir_Security_force_mode, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, 
970         {"force unknown acl user", P_BOOL, P_LOCAL, &sDefault.bForceUnknownAclUser, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE},
971         {"inherit permissions", P_BOOL, P_LOCAL, &sDefault.bInheritPerms, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
972         {"inherit acls", P_BOOL, P_LOCAL, &sDefault.bInheritACLS, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
973         {"inherit owner", P_BOOL, P_LOCAL, &sDefault.bInheritOwner, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
974         {"guest only", P_BOOL, P_LOCAL, &sDefault.bGuest_only, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
975         {"only guest", P_BOOL, P_LOCAL, &sDefault.bGuest_only, NULL, NULL, FLAG_HIDE}, 
976         {"hidden", P_BOOL, P_LOCAL, &sDefault.bHidden, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT},
977
978         {"guest ok", P_BOOL, P_LOCAL, &sDefault.bGuest_ok, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT}, 
979         {"public", P_BOOL, P_LOCAL, &sDefault.bGuest_ok, NULL, NULL, FLAG_HIDE}, 
980
981         {"only user", P_BOOL, P_LOCAL, &sDefault.bOnlyUser, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_DEPRECATED}, 
982         {"hosts allow", P_LIST, P_LOCAL, &sDefault.szHostsallow, NULL, NULL, FLAG_GLOBAL | FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT}, 
983         {"allow hosts", P_LIST, P_LOCAL, &sDefault.szHostsallow, NULL, NULL, FLAG_HIDE}, 
984         {"hosts deny", P_LIST, P_LOCAL, &sDefault.szHostsdeny, NULL, NULL, FLAG_GLOBAL | FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT}, 
985         {"deny hosts", P_LIST, P_LOCAL, &sDefault.szHostsdeny, NULL, NULL, FLAG_HIDE}, 
986         {"preload modules", P_LIST, P_GLOBAL, &Globals.szPreloadModules, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL}, 
987         {"use kerberos keytab", P_BOOL, P_GLOBAL, &Globals.bUseKerberosKeytab, NULL, NULL, FLAG_ADVANCED}, 
988
989         {N_("Logging Options"), P_SEP, P_SEPARATOR}, 
990
991         {"log level", P_STRING, P_GLOBAL, &Globals.szLogLevel, handle_debug_list, NULL, FLAG_ADVANCED}, 
992         {"debuglevel", P_STRING, P_GLOBAL, &Globals.szLogLevel, handle_debug_list, NULL, FLAG_HIDE}, 
993         {"syslog", P_INTEGER, P_GLOBAL, &Globals.syslog, NULL, NULL, FLAG_ADVANCED}, 
994         {"syslog only", P_BOOL, P_GLOBAL, &Globals.bSyslogOnly, NULL, NULL, FLAG_ADVANCED}, 
995         {"log file", P_STRING, P_GLOBAL, &Globals.szLogFile, NULL, NULL, FLAG_ADVANCED}, 
996
997         {"max log size", P_INTEGER, P_GLOBAL, &Globals.max_log_size, NULL, NULL, FLAG_ADVANCED}, 
998         {"debug timestamp", P_BOOL, P_GLOBAL, &Globals.bTimestampLogs, NULL, NULL, FLAG_ADVANCED}, 
999         {"timestamp logs", P_BOOL, P_GLOBAL, &Globals.bTimestampLogs, NULL, NULL, FLAG_ADVANCED}, 
1000         {"debug prefix timestamp", P_BOOL, P_GLOBAL, &Globals.bDebugPrefixTimestamp, NULL, NULL, FLAG_ADVANCED}, 
1001         {"debug hires timestamp", P_BOOL, P_GLOBAL, &Globals.bDebugHiresTimestamp, NULL, NULL, FLAG_ADVANCED}, 
1002         {"debug pid", P_BOOL, P_GLOBAL, &Globals.bDebugPid, NULL, NULL, FLAG_ADVANCED}, 
1003         {"debug uid", P_BOOL, P_GLOBAL, &Globals.bDebugUid, NULL, NULL, FLAG_ADVANCED}, 
1004         {"debug class", P_BOOL, P_GLOBAL, &Globals.bDebugClass, NULL, NULL, FLAG_ADVANCED},
1005         {"enable core files", P_BOOL, P_GLOBAL, &Globals.bEnableCoreFiles, NULL, NULL, FLAG_ADVANCED},
1006
1007         {N_("Protocol Options"), P_SEP, P_SEPARATOR}, 
1008
1009         {"allocation roundup size", P_INTEGER, P_LOCAL, &sDefault.iallocation_roundup_size, NULL, NULL, FLAG_ADVANCED}, 
1010         {"aio read size", P_INTEGER, P_LOCAL, &sDefault.iAioReadSize, NULL, NULL, FLAG_ADVANCED}, 
1011         {"aio write size", P_INTEGER, P_LOCAL, &sDefault.iAioWriteSize, NULL, NULL, FLAG_ADVANCED}, 
1012         {"aio write behind", P_STRING, P_LOCAL, &sDefault.szAioWriteBehind, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL }, 
1013         {"smb ports", P_STRING, P_GLOBAL, &Globals.smb_ports, NULL, NULL, FLAG_ADVANCED}, 
1014         {"large readwrite", P_BOOL, P_GLOBAL, &Globals.bLargeReadwrite, NULL, NULL, FLAG_ADVANCED}, 
1015         {"max protocol", P_ENUM, P_GLOBAL, &Globals.maxprotocol, NULL, enum_protocol, FLAG_ADVANCED}, 
1016         {"protocol", P_ENUM, P_GLOBAL, &Globals.maxprotocol, NULL, enum_protocol, FLAG_ADVANCED}, 
1017         {"min protocol", P_ENUM, P_GLOBAL, &Globals.minprotocol, NULL, enum_protocol, FLAG_ADVANCED}, 
1018         {"min receivefile size", P_INTEGER, P_GLOBAL, &Globals.iminreceivefile, NULL, NULL, FLAG_ADVANCED}, 
1019         {"read raw", P_BOOL, P_GLOBAL, &Globals.bReadRaw, NULL, NULL, FLAG_ADVANCED}, 
1020         {"write raw", P_BOOL, P_GLOBAL, &Globals.bWriteRaw, NULL, NULL, FLAG_ADVANCED}, 
1021         {"disable netbios", P_BOOL, P_GLOBAL, &Globals.bDisableNetbios, NULL, NULL, FLAG_ADVANCED}, 
1022         {"reset on zero vc", P_BOOL, P_GLOBAL, &Globals.bResetOnZeroVC, NULL, NULL, FLAG_ADVANCED}, 
1023
1024         {"acl compatibility", P_ENUM, P_GLOBAL, &Globals.iAclCompat, NULL,  enum_acl_compat_vals, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1025         {"defer sharing violations", P_BOOL, P_GLOBAL, &Globals.bDeferSharingViolations, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL},
1026         {"ea support", P_BOOL, P_LOCAL, &sDefault.bEASupport, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1027         {"nt acl support", P_BOOL, P_LOCAL, &sDefault.bNTAclSupport, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1028         {"nt pipe support", P_BOOL, P_GLOBAL, &Globals.bNTPipeSupport, NULL, NULL, FLAG_ADVANCED}, 
1029         {"nt status support", P_BOOL, P_GLOBAL, &Globals.bNTStatusSupport, NULL, NULL, FLAG_ADVANCED}, 
1030         {"profile acls", P_BOOL, P_LOCAL, &sDefault.bProfileAcls, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, 
1031
1032         {"announce version", P_STRING, P_GLOBAL, &Globals.szAnnounceVersion, NULL, NULL, FLAG_ADVANCED}, 
1033         {"announce as", P_ENUM, P_GLOBAL, &Globals.announce_as, NULL, enum_announce_as,  FLAG_ADVANCED}, 
1034         {"map acl inherit", P_BOOL, P_LOCAL, &sDefault.bMap_acl_inherit, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1035         {"afs share", P_BOOL, P_LOCAL, &sDefault.bAfs_Share, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL},
1036         {"max mux", P_INTEGER, P_GLOBAL, &Globals.max_mux, NULL, NULL, FLAG_ADVANCED}, 
1037         {"max xmit", P_INTEGER, P_GLOBAL, &Globals.max_xmit, NULL, NULL, FLAG_ADVANCED}, 
1038
1039         {"name resolve order", P_STRING, P_GLOBAL, &Globals.szNameResolveOrder, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD}, 
1040         {"max ttl", P_INTEGER, P_GLOBAL, &Globals.max_ttl, NULL, NULL, FLAG_ADVANCED}, 
1041         {"max wins ttl", P_INTEGER, P_GLOBAL, &Globals.max_wins_ttl, NULL, NULL, FLAG_ADVANCED}, 
1042         {"min wins ttl", P_INTEGER, P_GLOBAL, &Globals.min_wins_ttl, NULL, NULL, FLAG_ADVANCED}, 
1043         {"time server", P_BOOL, P_GLOBAL, &Globals.bTimeServer, NULL, NULL, FLAG_ADVANCED}, 
1044         {"unix extensions", P_BOOL, P_GLOBAL, &Globals.bUnixExtensions, NULL, NULL, FLAG_ADVANCED}, 
1045         {"use spnego", P_BOOL, P_GLOBAL, &Globals.bUseSpnego, NULL, NULL, FLAG_ADVANCED}, 
1046         {"client signing", P_ENUM, P_GLOBAL, &Globals.client_signing, NULL, enum_smb_signing_vals, FLAG_ADVANCED}, 
1047         {"server signing", P_ENUM, P_GLOBAL, &Globals.server_signing, NULL, enum_smb_signing_vals, FLAG_ADVANCED}, 
1048         {"smb encrypt", P_ENUM, P_LOCAL, &sDefault.ismb_encrypt, NULL, enum_smb_signing_vals, FLAG_ADVANCED},
1049         {"client use spnego", P_BOOL, P_GLOBAL, &Globals.bClientUseSpnego, NULL, NULL, FLAG_ADVANCED}, 
1050         {"client ldap sasl wrapping", P_ENUM, P_GLOBAL, &Globals.client_ldap_sasl_wrapping, NULL, enum_ldap_sasl_wrapping, FLAG_ADVANCED},
1051         {"enable asu support", P_BOOL, P_GLOBAL, &Globals.bASUSupport, NULL, NULL, FLAG_ADVANCED}, 
1052         {"svcctl list", P_LIST, P_GLOBAL, &Globals.szServicesList, NULL, NULL, FLAG_ADVANCED},
1053
1054         {N_("Tuning Options"), P_SEP, P_SEPARATOR}, 
1055
1056         {"block size", P_INTEGER, P_LOCAL, &sDefault.iBlock_size, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1057         {"deadtime", P_INTEGER, P_GLOBAL, &Globals.deadtime, NULL, NULL, FLAG_ADVANCED}, 
1058         {"getwd cache", P_BOOL, P_GLOBAL, &Globals.getwd_cache, NULL, NULL, FLAG_ADVANCED},
1059         {"keepalive", P_INTEGER, P_GLOBAL, &Globals.iKeepalive, NULL, NULL, FLAG_ADVANCED},
1060         {"change notify", P_BOOL, P_LOCAL, &sDefault.bChangeNotify, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE },
1061         {"directory name cache size", P_INTEGER, P_LOCAL, &sDefault.iDirectoryNameCacheSize, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE },
1062         {"kernel change notify", P_BOOL, P_LOCAL, &sDefault.bKernelChangeNotify, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE },
1063
1064         {"lpq cache time", P_INTEGER, P_GLOBAL, &Globals.lpqcachetime, NULL, NULL, FLAG_ADVANCED}, 
1065         {"max smbd processes", P_INTEGER, P_GLOBAL, &Globals.iMaxSmbdProcesses, NULL, NULL, FLAG_ADVANCED}, 
1066         {"max connections", P_INTEGER, P_LOCAL, &sDefault.iMaxConnections, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
1067         {"paranoid server security", P_BOOL, P_GLOBAL, &Globals.paranoid_server_security, NULL, NULL, FLAG_ADVANCED}, 
1068         {"max disk size", P_INTEGER, P_GLOBAL, &Globals.maxdisksize, NULL, NULL, FLAG_ADVANCED}, 
1069         {"max open files", P_INTEGER, P_GLOBAL, &Globals.max_open_files, NULL, NULL, FLAG_ADVANCED}, 
1070         {"min print space", P_INTEGER, P_LOCAL, &sDefault.iMinPrintSpace, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT}, 
1071
1072         {"socket options", P_STRING, P_GLOBAL, &Globals.szSocketOptions, NULL, NULL, FLAG_ADVANCED},
1073         {"strict allocate", P_BOOL, P_LOCAL, &sDefault.bStrictAllocate, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
1074         {"strict sync", P_BOOL, P_LOCAL, &sDefault.bStrictSync, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
1075         {"sync always", P_BOOL, P_LOCAL, &sDefault.bSyncAlways, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
1076         {"use mmap", P_BOOL, P_GLOBAL, &Globals.bUseMmap, NULL, NULL, FLAG_ADVANCED}, 
1077         {"use sendfile", P_BOOL, P_LOCAL, &sDefault.bUseSendfile, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
1078         {"hostname lookups", P_BOOL, P_GLOBAL, &Globals.bHostnameLookups, NULL, NULL, FLAG_ADVANCED}, 
1079         {"write cache size", P_INTEGER, P_LOCAL, &sDefault.iWriteCacheSize, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_DEPRECATED}, 
1080
1081         {"name cache timeout", P_INTEGER, P_GLOBAL, &Globals.name_cache_timeout, NULL, NULL, FLAG_ADVANCED}, 
1082         {"ctdbd socket", P_STRING, P_GLOBAL, &Globals.ctdbdSocket, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL}, 
1083         {"cluster addresses", P_LIST, P_GLOBAL, &Globals.szClusterAddresses, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL}, 
1084         {"clustering", P_BOOL, P_GLOBAL, &Globals.clustering, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL}, 
1085
1086         {N_("Printing Options"), P_SEP, P_SEPARATOR}, 
1087
1088         {"max reported print jobs", P_INTEGER, P_LOCAL, &sDefault.iMaxReportedPrintJobs, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT}, 
1089         {"max print jobs", P_INTEGER, P_LOCAL, &sDefault.iMaxPrintJobs, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT}, 
1090         {"load printers", P_BOOL, P_GLOBAL, &Globals.bLoadPrinters, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT}, 
1091         {"printcap cache time", P_INTEGER, P_GLOBAL, &Globals.PrintcapCacheTime, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT}, 
1092         {"printcap name", P_STRING, P_GLOBAL, &Globals.szPrintcapname, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT}, 
1093         {"printcap", P_STRING, P_GLOBAL, &Globals.szPrintcapname, NULL, NULL, FLAG_HIDE}, 
1094         {"printable", P_BOOL, P_LOCAL, &sDefault.bPrint_ok, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT}, 
1095         {"print ok", P_BOOL, P_LOCAL, &sDefault.bPrint_ok, NULL, NULL, FLAG_HIDE}, 
1096         {"printing", P_ENUM, P_LOCAL, &sDefault.iPrinting, handle_printing, enum_printing, FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL}, 
1097         {"cups options", P_STRING, P_LOCAL, &sDefault.szCupsOptions, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL}, 
1098         {"cups server", P_STRING, P_GLOBAL, &Globals.szCupsServer, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL}, 
1099         {"iprint server", P_STRING, P_GLOBAL, &Globals.szIPrintServer, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL}, 
1100         {"print command", P_STRING, P_LOCAL, &sDefault.szPrintcommand, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL}, 
1101         {"disable spoolss", P_BOOL, P_GLOBAL, &Globals.bDisableSpoolss, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL}, 
1102         {"enable spoolss", P_BOOLREV, P_GLOBAL, &Globals.bDisableSpoolss, NULL, NULL, FLAG_HIDE}, 
1103         {"lpq command", P_STRING, P_LOCAL, &sDefault.szLpqcommand, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL}, 
1104         {"lprm command", P_STRING, P_LOCAL, &sDefault.szLprmcommand, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL}, 
1105         {"lppause command", P_STRING, P_LOCAL, &sDefault.szLppausecommand, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL}, 
1106         {"lpresume command", P_STRING, P_LOCAL, &sDefault.szLpresumecommand, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL}, 
1107         {"queuepause command", P_STRING, P_LOCAL, &sDefault.szQueuepausecommand, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL}, 
1108         {"queueresume command", P_STRING, P_LOCAL, &sDefault.szQueueresumecommand, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL}, 
1109
1110         {"addport command", P_STRING, P_GLOBAL, &Globals.szAddPortCommand, NULL, NULL, FLAG_ADVANCED}, 
1111         {"enumports command", P_STRING, P_GLOBAL, &Globals.szEnumPortsCommand, NULL, NULL, FLAG_ADVANCED}, 
1112         {"addprinter command", P_STRING, P_GLOBAL, &Globals.szAddPrinterCommand, NULL, NULL, FLAG_ADVANCED}, 
1113         {"deleteprinter command", P_STRING, P_GLOBAL, &Globals.szDeletePrinterCommand, NULL, NULL, FLAG_ADVANCED}, 
1114         {"show add printer wizard", P_BOOL, P_GLOBAL, &Globals.bMsAddPrinterWizard, NULL, NULL, FLAG_ADVANCED}, 
1115         {"os2 driver map", P_STRING, P_GLOBAL, &Globals.szOs2DriverMap, NULL, NULL, FLAG_ADVANCED}, 
1116
1117         {"printer name", P_STRING, P_LOCAL, &sDefault.szPrintername, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT}, 
1118         {"printer", P_STRING, P_LOCAL, &sDefault.szPrintername, NULL, NULL, FLAG_HIDE}, 
1119         {"use client driver", P_BOOL, P_LOCAL, &sDefault.bUseClientDriver, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT}, 
1120         {"default devmode", P_BOOL, P_LOCAL, &sDefault.bDefaultDevmode, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT}, 
1121         {"force printername", P_BOOL, P_LOCAL, &sDefault.bForcePrintername, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT}, 
1122         {"printjob username", P_STRING, P_LOCAL, &sDefault.szPrintjobUsername, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT},
1123
1124         {N_("Filename Handling"), P_SEP, P_SEPARATOR}, 
1125         {"mangling method", P_STRING, P_GLOBAL, &Globals.szManglingMethod, NULL, NULL, FLAG_ADVANCED}, 
1126         {"mangle prefix", P_INTEGER, P_GLOBAL, &Globals.mangle_prefix, NULL, NULL, FLAG_ADVANCED}, 
1127
1128         {"default case", P_ENUM, P_LOCAL, &sDefault.iDefaultCase, NULL, enum_case, FLAG_ADVANCED | FLAG_SHARE}, 
1129         {"case sensitive", P_ENUM, P_LOCAL, &sDefault.iCaseSensitive, NULL, enum_bool_auto, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1130         {"casesignames", P_ENUM, P_LOCAL, &sDefault.iCaseSensitive, NULL, enum_bool_auto, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL | FLAG_HIDE}, 
1131         {"preserve case", P_BOOL, P_LOCAL, &sDefault.bCasePreserve, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1132         {"short preserve case", P_BOOL, P_LOCAL, &sDefault.bShortCasePreserve, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1133         {"mangling char", P_CHAR, P_LOCAL, &sDefault.magic_char, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1134         {"hide dot files", P_BOOL, P_LOCAL, &sDefault.bHideDotFiles, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1135         {"hide special files", P_BOOL, P_LOCAL, &sDefault.bHideSpecialFiles, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1136         {"hide unreadable", P_BOOL, P_LOCAL, &sDefault.bHideUnReadable, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1137         {"hide unwriteable files", P_BOOL, P_LOCAL, &sDefault.bHideUnWriteableFiles, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1138         {"delete veto files", P_BOOL, P_LOCAL, &sDefault.bDeleteVetoFiles, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1139         {"veto files", P_STRING, P_LOCAL, &sDefault.szVetoFiles, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL }, 
1140         {"hide files", P_STRING, P_LOCAL, &sDefault.szHideFiles, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL }, 
1141         {"veto oplock files", P_STRING, P_LOCAL, &sDefault.szVetoOplockFiles, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL }, 
1142         {"map archive", P_BOOL, P_LOCAL, &sDefault.bMap_archive, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1143         {"map hidden", P_BOOL, P_LOCAL, &sDefault.bMap_hidden, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1144         {"map system", P_BOOL, P_LOCAL, &sDefault.bMap_system, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1145         {"map readonly", P_ENUM, P_LOCAL, &sDefault.iMap_readonly, NULL, enum_map_readonly, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1146         {"mangled names", P_BOOL, P_LOCAL, &sDefault.bMangledNames, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1147         {"max stat cache size", P_INTEGER, P_GLOBAL, &Globals.iMaxStatCacheSize, NULL, NULL, FLAG_ADVANCED}, 
1148         {"stat cache", P_BOOL, P_GLOBAL, &Globals.bStatCache, NULL, NULL, FLAG_ADVANCED}, 
1149         {"store dos attributes", P_BOOL, P_LOCAL, &sDefault.bStoreDosAttributes, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1150         {"dmapi support", P_BOOL, P_LOCAL, &sDefault.bDmapiSupport, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL},
1151
1152
1153         {N_("Domain Options"), P_SEP, P_SEPARATOR}, 
1154
1155         {"machine password timeout", P_INTEGER, P_GLOBAL, &Globals.machine_password_timeout, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD}, 
1156
1157         {N_("Logon Options"), P_SEP, P_SEPARATOR}, 
1158
1159         {"add user script", P_STRING, P_GLOBAL, &Globals.szAddUserScript, NULL, NULL, FLAG_ADVANCED}, 
1160         {"rename user script", P_STRING, P_GLOBAL, &Globals.szRenameUserScript, NULL, NULL, FLAG_ADVANCED},
1161         {"delete user script", P_STRING, P_GLOBAL, &Globals.szDelUserScript, NULL, NULL, FLAG_ADVANCED}, 
1162         {"add group script", P_STRING, P_GLOBAL, &Globals.szAddGroupScript, NULL, NULL, FLAG_ADVANCED}, 
1163         {"delete group script", P_STRING, P_GLOBAL, &Globals.szDelGroupScript, NULL, NULL, FLAG_ADVANCED}, 
1164         {"add user to group script", P_STRING, P_GLOBAL, &Globals.szAddUserToGroupScript, NULL, NULL, FLAG_ADVANCED}, 
1165         {"delete user from group script", P_STRING, P_GLOBAL, &Globals.szDelUserFromGroupScript, NULL, NULL, FLAG_ADVANCED}, 
1166         {"set primary group script", P_STRING, P_GLOBAL, &Globals.szSetPrimaryGroupScript, NULL, NULL, FLAG_ADVANCED}, 
1167         {"add machine script", P_STRING, P_GLOBAL, &Globals.szAddMachineScript, NULL, NULL, FLAG_ADVANCED}, 
1168         {"shutdown script", P_STRING, P_GLOBAL, &Globals.szShutdownScript, NULL, NULL, FLAG_ADVANCED}, 
1169         {"abort shutdown script", P_STRING, P_GLOBAL, &Globals.szAbortShutdownScript, NULL, NULL, FLAG_ADVANCED}, 
1170         {"username map script", P_STRING, P_GLOBAL, &Globals.szUsernameMapScript, NULL, NULL, FLAG_ADVANCED}, 
1171
1172         {"logon script", P_STRING, P_GLOBAL, &Globals.szLogonScript, NULL, NULL, FLAG_ADVANCED}, 
1173         {"logon path", P_STRING, P_GLOBAL, &Globals.szLogonPath, NULL, NULL, FLAG_ADVANCED}, 
1174         {"logon drive", P_STRING, P_GLOBAL, &Globals.szLogonDrive, NULL, NULL, FLAG_ADVANCED}, 
1175         {"logon home", P_STRING, P_GLOBAL, &Globals.szLogonHome, NULL, NULL, FLAG_ADVANCED}, 
1176         {"domain logons", P_BOOL, P_GLOBAL, &Globals.bDomainLogons, NULL, NULL, FLAG_ADVANCED}, 
1177
1178         {N_("Browse Options"), P_SEP, P_SEPARATOR}, 
1179
1180         {"os level", P_INTEGER, P_GLOBAL, &Globals.os_level, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED}, 
1181         {"lm announce", P_ENUM, P_GLOBAL, &Globals.lm_announce, NULL, enum_bool_auto, FLAG_ADVANCED}, 
1182         {"lm interval", P_INTEGER, P_GLOBAL, &Globals.lm_interval, NULL, NULL, FLAG_ADVANCED}, 
1183         {"preferred master", P_ENUM, P_GLOBAL, &Globals.iPreferredMaster, NULL, enum_bool_auto, FLAG_BASIC | FLAG_ADVANCED}, 
1184         {"prefered master", P_ENUM, P_GLOBAL, &Globals.iPreferredMaster, NULL, enum_bool_auto, FLAG_HIDE}, 
1185         {"local master", P_BOOL, P_GLOBAL, &Globals.bLocalMaster, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED}, 
1186         {"domain master", P_ENUM, P_GLOBAL, &Globals.iDomainMaster, NULL, enum_bool_auto, FLAG_BASIC | FLAG_ADVANCED}, 
1187         {"browse list", P_BOOL, P_GLOBAL, &Globals.bBrowseList, NULL, NULL, FLAG_ADVANCED}, 
1188         {"browseable", P_BOOL, P_LOCAL, &sDefault.bBrowseable, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT}, 
1189         {"browsable", P_BOOL, P_LOCAL, &sDefault.bBrowseable, NULL, NULL, FLAG_HIDE}, 
1190         {"enhanced browsing", P_BOOL, P_GLOBAL, &Globals.enhanced_browsing, NULL, NULL, FLAG_ADVANCED}, 
1191
1192         {N_("WINS Options"), P_SEP, P_SEPARATOR}, 
1193
1194         {"dns proxy", P_BOOL, P_GLOBAL, &Globals.bDNSproxy, NULL, NULL, FLAG_ADVANCED}, 
1195         {"wins proxy", P_BOOL, P_GLOBAL, &Globals.bWINSproxy, NULL, NULL, FLAG_ADVANCED}, 
1196
1197         {"wins server", P_LIST, P_GLOBAL, &Globals.szWINSservers, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD}, 
1198         {"wins support", P_BOOL, P_GLOBAL, &Globals.bWINSsupport, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD}, 
1199         {"wins hook", P_STRING, P_GLOBAL, &Globals.szWINSHook, NULL, NULL, FLAG_ADVANCED}, 
1200
1201         {N_("Locking Options"), P_SEP, P_SEPARATOR}, 
1202
1203         {"blocking locks", P_BOOL, P_LOCAL, &sDefault.bBlockingLocks, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1204         {"csc policy", P_ENUM, P_LOCAL, &sDefault.iCSCPolicy, NULL, enum_csc_policy, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1205         {"fake oplocks", P_BOOL, P_LOCAL, &sDefault.bFakeOplocks, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
1206         {"kernel oplocks", P_BOOL, P_GLOBAL, &Globals.bKernelOplocks, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL}, 
1207         {"locking", P_BOOL, P_LOCAL, &sDefault.bLocking, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1208         {"lock spin time", P_INTEGER, P_GLOBAL, &Globals.iLockSpinTime, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL}, 
1209
1210         {"oplocks", P_BOOL, P_LOCAL, &sDefault.bOpLocks, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1211         {"level2 oplocks", P_BOOL, P_LOCAL, &sDefault.bLevel2OpLocks, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1212         {"oplock break wait time", P_INTEGER, P_GLOBAL, &Globals.oplock_break_wait_time, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL}, 
1213         {"oplock contention limit", P_INTEGER, P_LOCAL, &sDefault.iOplockContentionLimit, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1214         {"posix locking", P_BOOL, P_LOCAL, &sDefault.bPosixLocking, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1215         {"strict locking", P_ENUM, P_LOCAL, &sDefault.iStrictLocking, NULL, enum_bool_auto, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1216         {"share modes", P_BOOL, P_LOCAL,  &sDefault.bShareModes, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1217
1218         {N_("Ldap Options"), P_SEP, P_SEPARATOR}, 
1219
1220         {"ldap admin dn", P_STRING, P_GLOBAL, &Globals.szLdapAdminDn, NULL, NULL, FLAG_ADVANCED}, 
1221         {"ldap delete dn", P_BOOL, P_GLOBAL, &Globals.ldap_delete_dn, NULL, NULL, FLAG_ADVANCED}, 
1222         {"ldap group suffix", P_STRING, P_GLOBAL, &Globals.szLdapGroupSuffix, NULL, NULL, FLAG_ADVANCED}, 
1223         {"ldap idmap suffix", P_STRING, P_GLOBAL, &Globals.szLdapIdmapSuffix, NULL, NULL, FLAG_ADVANCED}, 
1224         {"ldap machine suffix", P_STRING, P_GLOBAL, &Globals.szLdapMachineSuffix, NULL, NULL, FLAG_ADVANCED}, 
1225         {"ldap passwd sync", P_ENUM, P_GLOBAL, &Globals.ldap_passwd_sync, NULL, enum_ldap_passwd_sync, FLAG_ADVANCED}, 
1226         {"ldap password sync", P_ENUM, P_GLOBAL, &Globals.ldap_passwd_sync, NULL, enum_ldap_passwd_sync, FLAG_HIDE}, 
1227         {"ldap replication sleep", P_INTEGER, P_GLOBAL, &Globals.ldap_replication_sleep, NULL, NULL, FLAG_ADVANCED},
1228         {"ldap suffix", P_STRING, P_GLOBAL, &Globals.szLdapSuffix, NULL, NULL, FLAG_ADVANCED}, 
1229         {"ldap ssl", P_ENUM, P_GLOBAL, &Globals.ldap_ssl, NULL, enum_ldap_ssl, FLAG_ADVANCED}, 
1230         {"ldap timeout", P_INTEGER, P_GLOBAL, &Globals.ldap_timeout, NULL, NULL, FLAG_ADVANCED},
1231         {"ldap page size", P_INTEGER, P_GLOBAL, &Globals.ldap_page_size, NULL, NULL, FLAG_ADVANCED},
1232         {"ldap user suffix", P_STRING, P_GLOBAL, &Globals.szLdapUserSuffix, NULL, NULL, FLAG_ADVANCED}, 
1233
1234         {"ldap debug level", P_INTEGER, P_GLOBAL, &Globals.ldap_debug_level, handle_ldap_debug_level, NULL, FLAG_ADVANCED},
1235         {"ldap debug threshold", P_INTEGER, P_GLOBAL, &Globals.ldap_debug_threshold, NULL, NULL, FLAG_ADVANCED},
1236
1237
1238         {N_("EventLog Options"), P_SEP, P_SEPARATOR}, 
1239         {"eventlog list",  P_LIST, P_GLOBAL, &Globals.szEventLogs, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, 
1240
1241         {N_("Miscellaneous Options"), P_SEP, P_SEPARATOR}, 
1242         {"add share command", P_STRING, P_GLOBAL, &Globals.szAddShareCommand, NULL, NULL, FLAG_ADVANCED}, 
1243         {"change share command", P_STRING, P_GLOBAL, &Globals.szChangeShareCommand, NULL, NULL, FLAG_ADVANCED}, 
1244         {"delete share command", P_STRING, P_GLOBAL, &Globals.szDeleteShareCommand, NULL, NULL, FLAG_ADVANCED}, 
1245
1246         {"config file", P_STRING, P_GLOBAL, &Globals.szConfigFile, NULL, NULL, FLAG_HIDE}, 
1247         {"preload", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL, NULL, FLAG_ADVANCED}, 
1248         {"auto services", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL, NULL, FLAG_ADVANCED}, 
1249         {"lock directory", P_STRING, P_GLOBAL, &Globals.szLockDir, NULL, NULL, FLAG_ADVANCED}, 
1250         {"lock dir", P_STRING, P_GLOBAL, &Globals.szLockDir, NULL, NULL, FLAG_HIDE}, 
1251         {"pid directory", P_STRING, P_GLOBAL, &Globals.szPidDir, NULL, NULL, FLAG_ADVANCED}, 
1252 #ifdef WITH_UTMP
1253         {"utmp directory", P_STRING, P_GLOBAL, &Globals.szUtmpDir, NULL, NULL, FLAG_ADVANCED}, 
1254         {"wtmp directory", P_STRING, P_GLOBAL, &Globals.szWtmpDir, NULL, NULL, FLAG_ADVANCED}, 
1255         {"utmp", P_BOOL, P_GLOBAL, &Globals.bUtmp, NULL, NULL, FLAG_ADVANCED}, 
1256 #endif
1257
1258         {"default service", P_STRING, P_GLOBAL, &Globals.szDefaultService, NULL, NULL, FLAG_ADVANCED}, 
1259         {"default", P_STRING, P_GLOBAL, &Globals.szDefaultService, NULL, NULL, FLAG_ADVANCED}, 
1260         {"message command", P_STRING, P_GLOBAL, &Globals.szMsgCommand, NULL, NULL, FLAG_ADVANCED}, 
1261         {"dfree cache time", P_INTEGER, P_LOCAL, &sDefault.iDfreeCacheTime, NULL, NULL, FLAG_ADVANCED}, 
1262         {"dfree command", P_STRING, P_LOCAL, &sDefault.szDfree, NULL, NULL, FLAG_ADVANCED}, 
1263         {"get quota command", P_STRING, P_GLOBAL, &Globals.szGetQuota, NULL, NULL, FLAG_ADVANCED}, 
1264         {"set quota command", P_STRING, P_GLOBAL, &Globals.szSetQuota, NULL, NULL, FLAG_ADVANCED}, 
1265         {"remote announce", P_STRING, P_GLOBAL, &Globals.szRemoteAnnounce, NULL, NULL, FLAG_ADVANCED}, 
1266         {"remote browse sync", P_STRING, P_GLOBAL, &Globals.szRemoteBrowseSync, NULL, NULL, FLAG_ADVANCED}, 
1267         {"socket address", P_STRING, P_GLOBAL, &Globals.szSocketAddress, NULL, NULL, FLAG_ADVANCED}, 
1268         {"homedir map", P_STRING, P_GLOBAL, &Globals.szNISHomeMapName, NULL, NULL, FLAG_ADVANCED}, 
1269         {"afs username map", P_STRING, P_GLOBAL, &Globals.szAfsUsernameMap, NULL, NULL, FLAG_ADVANCED}, 
1270         {"afs token lifetime", P_INTEGER, P_GLOBAL, &Globals.iAfsTokenLifetime, NULL, NULL, FLAG_ADVANCED},
1271         {"log nt token command", P_STRING, P_GLOBAL, &Globals.szLogNtTokenCommand, NULL, NULL, FLAG_ADVANCED},
1272         {"time offset", P_INTEGER, P_GLOBAL, &extra_time_offset, NULL, NULL, FLAG_ADVANCED}, 
1273         {"NIS homedir", P_BOOL, P_GLOBAL, &Globals.bNISHomeMap, NULL, NULL, FLAG_ADVANCED}, 
1274         {"-valid", P_BOOL, P_LOCAL, &sDefault.valid, NULL, NULL, FLAG_HIDE}, 
1275
1276         {"copy", P_STRING, P_LOCAL, &sDefault.szCopy, handle_copy, NULL, FLAG_HIDE}, 
1277         {"include", P_STRING, P_LOCAL, &sDefault.szInclude, handle_include, NULL, FLAG_HIDE}, 
1278         {"preexec", P_STRING, P_LOCAL, &sDefault.szPreExec, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT}, 
1279         {"exec", P_STRING, P_LOCAL, &sDefault.szPreExec, NULL, NULL, FLAG_ADVANCED}, 
1280
1281         {"preexec close", P_BOOL, P_LOCAL, &sDefault.bPreexecClose, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
1282         {"postexec", P_STRING, P_LOCAL, &sDefault.szPostExec, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT}, 
1283         {"root preexec", P_STRING, P_LOCAL, &sDefault.szRootPreExec, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT}, 
1284         {"root preexec close", P_BOOL, P_LOCAL, &sDefault.bRootpreexecClose, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
1285         {"root postexec", P_STRING, P_LOCAL, &sDefault.szRootPostExec, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT}, 
1286         {"available", P_BOOL, P_LOCAL, &sDefault.bAvailable, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT}, 
1287         {"registry shares", P_BOOL, P_GLOBAL, &Globals.bRegistryShares, NULL, NULL, FLAG_ADVANCED},
1288         {"usershare allow guests", P_BOOL, P_GLOBAL, &Globals.bUsershareAllowGuests, NULL, NULL, FLAG_ADVANCED},
1289         {"usershare max shares", P_INTEGER, P_GLOBAL, &Globals.iUsershareMaxShares, NULL, NULL, FLAG_ADVANCED},
1290         {"usershare owner only", P_BOOL, P_GLOBAL, &Globals.bUsershareOwnerOnly, NULL, NULL, FLAG_ADVANCED}, 
1291         {"usershare path", P_STRING, P_GLOBAL, &Globals.szUsersharePath, NULL, NULL, FLAG_ADVANCED},
1292         {"usershare prefix allow list", P_LIST, P_GLOBAL, &Globals.szUsersharePrefixAllowList, NULL, NULL, FLAG_ADVANCED}, 
1293         {"usershare prefix deny list", P_LIST, P_GLOBAL, &Globals.szUsersharePrefixDenyList, NULL, NULL, FLAG_ADVANCED}, 
1294         {"usershare template share", P_STRING, P_GLOBAL, &Globals.szUsershareTemplateShare, NULL, NULL, FLAG_ADVANCED},
1295         {"volume", P_STRING, P_LOCAL, &sDefault.volume, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE }, 
1296         {"fstype", P_STRING, P_LOCAL, &sDefault.fstype, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
1297         {"set directory", P_BOOLREV, P_LOCAL, &sDefault.bNo_set_dir, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
1298         {"wide links", P_BOOL, P_LOCAL, &sDefault.bWidelinks, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1299         {"follow symlinks", P_BOOL, P_LOCAL, &sDefault.bSymlinks, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1300         {"dont descend", P_STRING, P_LOCAL, &sDefault.szDontdescend, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
1301         {"magic script", P_STRING, P_LOCAL, &sDefault.szMagicScript, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
1302         {"magic output", P_STRING, P_LOCAL, &sDefault.szMagicOutput, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
1303         {"delete readonly", P_BOOL, P_LOCAL, &sDefault.bDeleteReadonly, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1304         {"dos filemode", P_BOOL, P_LOCAL, &sDefault.bDosFilemode, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1305         {"dos filetimes", P_BOOL, P_LOCAL, &sDefault.bDosFiletimes, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1306         {"dos filetime resolution", P_BOOL, P_LOCAL, &sDefault.bDosFiletimeResolution, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1307
1308         {"fake directory create times", P_BOOL, P_LOCAL, &sDefault.bFakeDirCreateTimes, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1309         {"panic action", P_STRING, P_GLOBAL, &Globals.szPanicAction, NULL, NULL, FLAG_ADVANCED}, 
1310
1311         {N_("VFS module options"), P_SEP, P_SEPARATOR}, 
1312
1313         {"vfs objects", P_LIST, P_LOCAL, &sDefault.szVfsObjects, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
1314         {"vfs object", P_LIST, P_LOCAL, &sDefault.szVfsObjects, NULL, NULL, FLAG_HIDE}, 
1315
1316
1317         {N_("MSDFS options"), P_SEP, P_SEPARATOR},
1318
1319         {"msdfs root", P_BOOL, P_LOCAL, &sDefault.bMSDfsRoot, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
1320         {"msdfs proxy", P_STRING, P_LOCAL, &sDefault.szMSDfsProxy, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
1321         {"host msdfs", P_BOOL, P_GLOBAL, &Globals.bHostMSDfs, NULL, NULL, FLAG_ADVANCED}, 
1322
1323         {N_("Winbind options"), P_SEP, P_SEPARATOR}, 
1324
1325         {"passdb expand explicit", P_BOOL, P_GLOBAL, &Globals.bPassdbExpandExplicit, NULL, NULL, FLAG_ADVANCED},
1326         {"idmap domains", P_LIST, P_GLOBAL, &Globals.szIdmapDomains, NULL, NULL, FLAG_ADVANCED}, 
1327         {"idmap backend", P_LIST, P_GLOBAL, &Globals.szIdmapBackend, NULL, NULL, FLAG_ADVANCED }, 
1328         {"idmap alloc backend", P_STRING, P_GLOBAL, &Globals.szIdmapAllocBackend, NULL, NULL, FLAG_ADVANCED}, 
1329         {"idmap cache time", P_INTEGER, P_GLOBAL, &Globals.iIdmapCacheTime, NULL, NULL, FLAG_ADVANCED}, 
1330         {"idmap negative cache time", P_INTEGER, P_GLOBAL, &Globals.iIdmapNegativeCacheTime, NULL, NULL, FLAG_ADVANCED}, 
1331         {"idmap uid", P_STRING, P_GLOBAL, &Globals.szIdmapUID, handle_idmap_uid, NULL, FLAG_ADVANCED }, 
1332         {"winbind uid", P_STRING, P_GLOBAL, &Globals.szIdmapUID, handle_idmap_uid, NULL, FLAG_HIDE }, 
1333         {"idmap gid", P_STRING, P_GLOBAL, &Globals.szIdmapGID, handle_idmap_gid, NULL, FLAG_ADVANCED }, 
1334         {"winbind gid", P_STRING, P_GLOBAL, &Globals.szIdmapGID, handle_idmap_gid, NULL, FLAG_HIDE }, 
1335         {"template homedir", P_STRING, P_GLOBAL, &Globals.szTemplateHomedir, NULL, NULL, FLAG_ADVANCED}, 
1336         {"template shell", P_STRING, P_GLOBAL, &Globals.szTemplateShell, NULL, NULL, FLAG_ADVANCED}, 
1337         {"winbind separator", P_STRING, P_GLOBAL, &Globals.szWinbindSeparator, NULL, NULL, FLAG_ADVANCED}, 
1338         {"winbind cache time", P_INTEGER, P_GLOBAL, &Globals.winbind_cache_time, NULL, NULL, FLAG_ADVANCED}, 
1339         {"winbind enum users", P_BOOL, P_GLOBAL, &Globals.bWinbindEnumUsers, NULL, NULL, FLAG_ADVANCED}, 
1340         {"winbind enum groups", P_BOOL, P_GLOBAL, &Globals.bWinbindEnumGroups, NULL, NULL, FLAG_ADVANCED}, 
1341         {"winbind use default domain", P_BOOL, P_GLOBAL, &Globals.bWinbindUseDefaultDomain, NULL, NULL, FLAG_ADVANCED}, 
1342         {"winbind trusted domains only", P_BOOL, P_GLOBAL, &Globals.bWinbindTrustedDomainsOnly, NULL, NULL, FLAG_ADVANCED}, 
1343         {"winbind nested groups", P_BOOL, P_GLOBAL, &Globals.bWinbindNestedGroups, NULL, NULL, FLAG_ADVANCED}, 
1344         {"winbind expand groups", P_INTEGER, P_GLOBAL, &Globals.winbind_expand_groups, NULL, NULL, FLAG_ADVANCED}, 
1345         {"winbind nss info", P_LIST, P_GLOBAL, &Globals.szWinbindNssInfo, NULL, NULL, FLAG_ADVANCED}, 
1346         {"winbind refresh tickets", P_BOOL, P_GLOBAL, &Globals.bWinbindRefreshTickets, NULL, NULL, FLAG_ADVANCED}, 
1347         {"winbind offline logon", P_BOOL, P_GLOBAL, &Globals.bWinbindOfflineLogon, NULL, NULL, FLAG_ADVANCED},
1348         {"winbind normalize names", P_BOOL, P_GLOBAL, &Globals.bWinbindNormalizeNames, NULL, NULL, FLAG_ADVANCED},
1349         {"winbind rpc only", P_BOOL, P_GLOBAL, &Globals.bWinbindRpcOnly, NULL, NULL, FLAG_ADVANCED},
1350
1351         {NULL,  P_BOOL,  P_NONE,  NULL,  NULL,  NULL,  0}
1352 };
1353
1354 /***************************************************************************
1355  Initialise the sDefault parameter structure for the printer values.
1356 ***************************************************************************/
1357
1358 static void init_printer_values(service *pService)
1359 {
1360         /* choose defaults depending on the type of printing */
1361         switch (pService->iPrinting) {
1362                 case PRINT_BSD:
1363                 case PRINT_AIX:
1364                 case PRINT_LPRNT:
1365                 case PRINT_LPROS2:
1366                         string_set(&pService->szLpqcommand, "lpq -P'%p'");
1367                         string_set(&pService->szLprmcommand, "lprm -P'%p' %j");
1368                         string_set(&pService->szPrintcommand, "lpr -r -P'%p' %s");
1369                         break;
1370
1371                 case PRINT_LPRNG:
1372                 case PRINT_PLP:
1373                         string_set(&pService->szLpqcommand, "lpq -P'%p'");
1374                         string_set(&pService->szLprmcommand, "lprm -P'%p' %j");
1375                         string_set(&pService->szPrintcommand, "lpr -r -P'%p' %s");
1376                         string_set(&pService->szQueuepausecommand, "lpc stop '%p'");
1377                         string_set(&pService->szQueueresumecommand, "lpc start '%p'");
1378                         string_set(&pService->szLppausecommand, "lpc hold '%p' %j");
1379                         string_set(&pService->szLpresumecommand, "lpc release '%p' %j");
1380                         break;
1381
1382                 case PRINT_CUPS:
1383                 case PRINT_IPRINT:
1384 #ifdef HAVE_CUPS
1385                         /* set the lpq command to contain the destination printer
1386                            name only.  This is used by cups_queue_get() */
1387                         string_set(&pService->szLpqcommand, "%p");
1388                         string_set(&pService->szLprmcommand, "");
1389                         string_set(&pService->szPrintcommand, "");
1390                         string_set(&pService->szLppausecommand, "");
1391                         string_set(&pService->szLpresumecommand, "");
1392                         string_set(&pService->szQueuepausecommand, "");
1393                         string_set(&pService->szQueueresumecommand, "");
1394 #else
1395                         string_set(&pService->szLpqcommand, "lpq -P'%p'");
1396                         string_set(&pService->szLprmcommand, "lprm -P'%p' %j");
1397                         string_set(&pService->szPrintcommand, "lpr -P'%p' %s; rm %s");
1398                         string_set(&pService->szLppausecommand, "lp -i '%p-%j' -H hold");
1399                         string_set(&pService->szLpresumecommand, "lp -i '%p-%j' -H resume");
1400                         string_set(&pService->szQueuepausecommand, "disable '%p'");
1401                         string_set(&pService->szQueueresumecommand, "enable '%p'");
1402 #endif /* HAVE_CUPS */
1403                         break;
1404
1405                 case PRINT_SYSV:
1406                 case PRINT_HPUX:
1407                         string_set(&pService->szLpqcommand, "lpstat -o%p");
1408                         string_set(&pService->szLprmcommand, "cancel %p-%j");
1409                         string_set(&pService->szPrintcommand, "lp -c -d%p %s; rm %s");
1410                         string_set(&pService->szQueuepausecommand, "disable %p");
1411                         string_set(&pService->szQueueresumecommand, "enable %p");
1412 #ifndef HPUX
1413                         string_set(&pService->szLppausecommand, "lp -i %p-%j -H hold");
1414                         string_set(&pService->szLpresumecommand, "lp -i %p-%j -H resume");
1415 #endif /* HPUX */
1416                         break;
1417
1418                 case PRINT_QNX:
1419                         string_set(&pService->szLpqcommand, "lpq -P%p");
1420                         string_set(&pService->szLprmcommand, "lprm -P%p %j");
1421                         string_set(&pService->szPrintcommand, "lp -r -P%p %s");
1422                         break;
1423
1424 #ifdef DEVELOPER
1425         case PRINT_TEST:
1426         case PRINT_VLP:
1427                 string_set(&pService->szPrintcommand, "vlp print %p %s");
1428                 string_set(&pService->szLpqcommand, "vlp lpq %p");
1429                 string_set(&pService->szLprmcommand, "vlp lprm %p %j");
1430                 string_set(&pService->szLppausecommand, "vlp lppause %p %j");
1431                 string_set(&pService->szLpresumecommand, "vlp lpresum %p %j");
1432                 string_set(&pService->szQueuepausecommand, "vlp queuepause %p");
1433                 string_set(&pService->szQueueresumecommand, "vlp queueresume %p");
1434                 break;
1435 #endif /* DEVELOPER */
1436
1437         }
1438 }
1439
1440 /***************************************************************************
1441  Initialise the global parameter structure.
1442 ***************************************************************************/
1443
1444 static void init_globals(bool first_time_only)
1445 {
1446         static bool done_init = False;
1447         char *s = NULL;
1448
1449         /* If requested to initialize only once and we've already done it... */
1450         if (first_time_only && done_init) {
1451                 /* ... then we have nothing more to do */
1452                 return;
1453         }
1454
1455         if (!done_init) {
1456                 int i;
1457
1458                 /* The logfile can be set before this is invoked. Free it if so. */
1459                 if (Globals.szLogFile != NULL) {
1460                         string_free(&Globals.szLogFile);
1461                         Globals.szLogFile = NULL;
1462                 }
1463
1464                 memset((void *)&Globals, '\0', sizeof(Globals));
1465
1466                 for (i = 0; parm_table[i].label; i++)
1467                         if ((parm_table[i].type == P_STRING ||
1468                              parm_table[i].type == P_USTRING) &&
1469                             parm_table[i].ptr)
1470                                 string_set((char **)parm_table[i].ptr, "");
1471
1472                 string_set(&sDefault.fstype, FSTYPE_STRING);
1473                 string_set(&sDefault.szPrintjobUsername, "%U");
1474
1475                 init_printer_values(&sDefault);
1476
1477                 done_init = True;
1478         }
1479
1480
1481         DEBUG(3, ("Initialising global parameters\n"));
1482
1483         string_set(&Globals.szSMBPasswdFile, get_dyn_SMB_PASSWD_FILE());
1484         string_set(&Globals.szPrivateDir, get_dyn_PRIVATE_DIR());
1485
1486         /* use the new 'hash2' method by default, with a prefix of 1 */
1487         string_set(&Globals.szManglingMethod, "hash2");
1488         Globals.mangle_prefix = 1;
1489
1490         string_set(&Globals.szGuestaccount, GUEST_ACCOUNT);
1491
1492         /* using UTF8 by default allows us to support all chars */
1493         string_set(&Globals.unix_charset, DEFAULT_UNIX_CHARSET);
1494
1495 #if defined(HAVE_NL_LANGINFO) && defined(CODESET)
1496         /* If the system supports nl_langinfo(), try to grab the value
1497            from the user's locale */
1498         string_set(&Globals.display_charset, "LOCALE");
1499 #else
1500         string_set(&Globals.display_charset, DEFAULT_DISPLAY_CHARSET);
1501 #endif
1502
1503         /* Use codepage 850 as a default for the dos character set */
1504         string_set(&Globals.dos_charset, DEFAULT_DOS_CHARSET);
1505
1506         /*
1507          * Allow the default PASSWD_CHAT to be overridden in local.h.
1508          */
1509         string_set(&Globals.szPasswdChat, DEFAULT_PASSWD_CHAT);
1510
1511         set_global_myname(myhostname());
1512         string_set(&Globals.szNetbiosName,global_myname());
1513
1514         set_global_myworkgroup(WORKGROUP);
1515         string_set(&Globals.szWorkgroup, lp_workgroup());
1516
1517         string_set(&Globals.szPasswdProgram, "");
1518         string_set(&Globals.szPidDir, get_dyn_PIDDIR());
1519         string_set(&Globals.szLockDir, get_dyn_LOCKDIR());
1520         string_set(&Globals.szSocketAddress, "0.0.0.0");
1521
1522         if (asprintf(&s, "Samba %s", SAMBA_VERSION_STRING) < 0) {
1523                 smb_panic("init_globals: ENOMEM");
1524         }
1525         string_set(&Globals.szServerString, s);
1526         SAFE_FREE(s);
1527         if (asprintf(&s, "%d.%d", DEFAULT_MAJOR_VERSION,
1528                         DEFAULT_MINOR_VERSION) < 0) {
1529                 smb_panic("init_globals: ENOMEM");
1530         }
1531         string_set(&Globals.szAnnounceVersion, s);
1532         SAFE_FREE(s);
1533 #ifdef DEVELOPER
1534         string_set(&Globals.szPanicAction, "/bin/sleep 999999999");
1535 #endif
1536
1537         string_set(&Globals.szSocketOptions, DEFAULT_SOCKET_OPTIONS);
1538
1539         string_set(&Globals.szLogonDrive, "");
1540         /* %N is the NIS auto.home server if -DAUTOHOME is used, else same as %L */
1541         string_set(&Globals.szLogonHome, "\\\\%N\\%U");
1542         string_set(&Globals.szLogonPath, "\\\\%N\\%U\\profile");
1543
1544         string_set(&Globals.szNameResolveOrder, "lmhosts wins host bcast");
1545         string_set(&Globals.szPasswordServer, "*");
1546
1547         Globals.AlgorithmicRidBase = BASE_RID;
1548
1549         Globals.bLoadPrinters = True;
1550         Globals.PrintcapCacheTime = 750;        /* 12.5 minutes */
1551
1552         Globals.ConfigBackend = config_backend;
1553
1554         /* Was 65535 (0xFFFF). 0x4101 matches W2K and causes major speed improvements... */
1555         /* Discovered by 2 days of pain by Don McCall @ HP :-). */
1556         Globals.max_xmit = 0x4104;
1557         Globals.max_mux = 50;   /* This is *needed* for profile support. */
1558         Globals.lpqcachetime = 30;      /* changed to handle large print servers better -- jerry */
1559         Globals.bDisableSpoolss = False;
1560         Globals.iMaxSmbdProcesses = 0;/* no limit specified */
1561         Globals.pwordlevel = 0;
1562         Globals.unamelevel = 0;
1563         Globals.deadtime = 0;
1564         Globals.getwd_cache = true;
1565         Globals.bLargeReadwrite = True;
1566         Globals.max_log_size = 5000;
1567         Globals.max_open_files = MAX_OPEN_FILES;
1568         Globals.open_files_db_hash_size = SMB_OPEN_DATABASE_TDB_HASH_SIZE;
1569         Globals.maxprotocol = PROTOCOL_NT1;
1570         Globals.minprotocol = PROTOCOL_CORE;
1571         Globals.security = SEC_USER;
1572         Globals.paranoid_server_security = True;
1573         Globals.bEncryptPasswords = True;
1574         Globals.bUpdateEncrypt = False;
1575         Globals.clientSchannel = Auto;
1576         Globals.serverSchannel = Auto;
1577         Globals.bReadRaw = True;
1578         Globals.bWriteRaw = True;
1579         Globals.bNullPasswords = False;
1580         Globals.bObeyPamRestrictions = False;
1581         Globals.syslog = 1;
1582         Globals.bSyslogOnly = False;
1583         Globals.bTimestampLogs = True;
1584         string_set(&Globals.szLogLevel, "0");
1585         Globals.bDebugPrefixTimestamp = False;
1586         Globals.bDebugHiresTimestamp = False;
1587         Globals.bDebugPid = False;
1588         Globals.bDebugUid = False;
1589         Globals.bDebugClass = False;
1590         Globals.bEnableCoreFiles = True;
1591         Globals.max_ttl = 60 * 60 * 24 * 3;     /* 3 days default. */
1592         Globals.max_wins_ttl = 60 * 60 * 24 * 6;        /* 6 days default. */
1593         Globals.min_wins_ttl = 60 * 60 * 6;     /* 6 hours default. */
1594         Globals.machine_password_timeout = 60 * 60 * 24 * 7;    /* 7 days default. */
1595         Globals.lm_announce = 2;        /* = Auto: send only if LM clients found */
1596         Globals.lm_interval = 60;
1597         Globals.announce_as = ANNOUNCE_AS_NT_SERVER;
1598 #if (defined(HAVE_NETGROUP) && defined(WITH_AUTOMOUNT))
1599         Globals.bNISHomeMap = False;
1600 #ifdef WITH_NISPLUS_HOME
1601         string_set(&Globals.szNISHomeMapName, "auto_home.org_dir");
1602 #else
1603         string_set(&Globals.szNISHomeMapName, "auto.home");
1604 #endif
1605 #endif
1606         Globals.bTimeServer = False;
1607         Globals.bBindInterfacesOnly = False;
1608         Globals.bUnixPasswdSync = False;
1609         Globals.bPamPasswordChange = False;
1610         Globals.bPasswdChatDebug = False;
1611         Globals.iPasswdChatTimeout = 2; /* 2 second default. */
1612         Globals.bNTPipeSupport = True;  /* Do NT pipes by default. */
1613         Globals.bNTStatusSupport = True; /* Use NT status by default. */
1614         Globals.bStatCache = True;      /* use stat cache by default */
1615         Globals.iMaxStatCacheSize = 256; /* 256k by default */
1616         Globals.restrict_anonymous = 0;
1617         Globals.bClientLanManAuth = False;      /* Do NOT use the LanMan hash if it is available */
1618         Globals.bClientPlaintextAuth = False;   /* Do NOT use a plaintext password even if is requested by the server */
1619         Globals.bLanmanAuth = False;    /* Do NOT use the LanMan hash, even if it is supplied */
1620         Globals.bNTLMAuth = True;       /* Do use NTLMv1 if it is supplied by the client (otherwise NTLMv2) */
1621         Globals.bClientNTLMv2Auth = False; /* Client should not use NTLMv2, as we can't tell that the server supports it. */
1622         /* Note, that we will use NTLM2 session security (which is different), if it is available */
1623
1624         Globals.map_to_guest = 0;       /* By Default, "Never" */
1625         Globals.oplock_break_wait_time = 0;     /* By Default, 0 msecs. */
1626         Globals.enhanced_browsing = true;
1627         Globals.iLockSpinTime = WINDOWS_MINIMUM_LOCK_TIMEOUT_MS; /* msec. */
1628 #ifdef MMAP_BLACKLIST
1629         Globals.bUseMmap = False;
1630 #else
1631         Globals.bUseMmap = True;
1632 #endif
1633         Globals.bUnixExtensions = True;
1634         Globals.bResetOnZeroVC = False;
1635
1636         /* hostname lookups can be very expensive and are broken on
1637            a large number of sites (tridge) */
1638         Globals.bHostnameLookups = False;
1639
1640         string_set(&Globals.szPassdbBackend, "smbpasswd");
1641         string_set(&Globals.szLdapSuffix, "");
1642         string_set(&Globals.szLdapMachineSuffix, "");
1643         string_set(&Globals.szLdapUserSuffix, "");
1644         string_set(&Globals.szLdapGroupSuffix, "");
1645         string_set(&Globals.szLdapIdmapSuffix, "");
1646
1647         string_set(&Globals.szLdapAdminDn, "");
1648         Globals.ldap_ssl = LDAP_SSL_ON;
1649         Globals.ldap_passwd_sync = LDAP_PASSWD_SYNC_OFF;
1650         Globals.ldap_delete_dn = False;
1651         Globals.ldap_replication_sleep = 1000; /* wait 1 sec for replication */
1652         Globals.ldap_timeout = LDAP_CONNECT_DEFAULT_TIMEOUT;
1653         Globals.ldap_page_size = LDAP_PAGE_SIZE;
1654
1655         Globals.ldap_debug_level = 0;
1656         Globals.ldap_debug_threshold = 10;
1657
1658         /* This is what we tell the afs client. in reality we set the token 
1659          * to never expire, though, when this runs out the afs client will 
1660          * forget the token. Set to 0 to get NEVERDATE.*/
1661         Globals.iAfsTokenLifetime = 604800;
1662
1663 /* these parameters are set to defaults that are more appropriate
1664    for the increasing samba install base:
1665
1666    as a member of the workgroup, that will possibly become a
1667    _local_ master browser (lm = True).  this is opposed to a forced
1668    local master browser startup (pm = True).
1669
1670    doesn't provide WINS server service by default (wsupp = False),
1671    and doesn't provide domain master browser services by default, either.
1672
1673 */
1674
1675         Globals.bMsAddPrinterWizard = True;
1676         Globals.os_level = 20;
1677         Globals.bLocalMaster = True;
1678         Globals.iDomainMaster = Auto;   /* depending on bDomainLogons */
1679         Globals.bDomainLogons = False;
1680         Globals.bBrowseList = True;
1681         Globals.bWINSsupport = False;
1682         Globals.bWINSproxy = False;
1683
1684         Globals.bDNSproxy = True;
1685
1686         /* this just means to use them if they exist */
1687         Globals.bKernelOplocks = True;
1688
1689         Globals.bAllowTrustedDomains = True;
1690
1691         string_set(&Globals.szTemplateShell, "/bin/false");
1692         string_set(&Globals.szTemplateHomedir, "/home/%D/%U");
1693         string_set(&Globals.szWinbindSeparator, "\\");
1694
1695         string_set(&Globals.szCupsServer, "");
1696         string_set(&Globals.szIPrintServer, "");
1697
1698         string_set(&Globals.ctdbdSocket, "");
1699         Globals.szClusterAddresses = NULL;
1700         Globals.clustering = False;
1701
1702         Globals.winbind_cache_time = 300;       /* 5 minutes */
1703         Globals.bWinbindEnumUsers = False;
1704         Globals.bWinbindEnumGroups = False;
1705         Globals.bWinbindUseDefaultDomain = False;
1706         Globals.bWinbindTrustedDomainsOnly = False;
1707         Globals.bWinbindNestedGroups = True;
1708         Globals.winbind_expand_groups = 1;
1709         Globals.szWinbindNssInfo = str_list_make(NULL, "template", NULL);
1710         Globals.bWinbindRefreshTickets = False;
1711         Globals.bWinbindOfflineLogon = False;
1712
1713         Globals.iIdmapCacheTime = 900; /* 15 minutes by default */
1714         Globals.iIdmapNegativeCacheTime = 120; /* 2 minutes by default */
1715
1716         Globals.bPassdbExpandExplicit = False;
1717
1718         Globals.name_cache_timeout = 660; /* In seconds */
1719
1720         Globals.bUseSpnego = True;
1721         Globals.bClientUseSpnego = True;
1722
1723         Globals.client_signing = Auto;
1724         Globals.server_signing = False;
1725
1726         Globals.bDeferSharingViolations = True;
1727         string_set(&Globals.smb_ports, SMB_PORTS);
1728
1729         Globals.bEnablePrivileges = True;
1730         Globals.bHostMSDfs        = True;
1731         Globals.bASUSupport       = False;
1732
1733         /* User defined shares. */
1734         if (asprintf(&s, "%s/usershares", get_dyn_STATEDIR()) < 0) {
1735                 smb_panic("init_globals: ENOMEM");
1736         }
1737         string_set(&Globals.szUsersharePath, s);
1738         SAFE_FREE(s);
1739         string_set(&Globals.szUsershareTemplateShare, "");
1740         Globals.iUsershareMaxShares = 0;
1741         /* By default disallow sharing of directories not owned by the sharer. */
1742         Globals.bUsershareOwnerOnly = True;
1743         /* By default disallow guest access to usershares. */
1744         Globals.bUsershareAllowGuests = False;
1745
1746         Globals.iKeepalive = DEFAULT_KEEPALIVE;
1747
1748         /* By default no shares out of the registry */
1749         Globals.bRegistryShares = False;
1750
1751         Globals.iminreceivefile = 0;
1752 }
1753
1754 /*******************************************************************
1755  Convenience routine to grab string parameters into temporary memory
1756  and run standard_sub_basic on them. The buffers can be written to by
1757  callers without affecting the source string.
1758 ********************************************************************/
1759
1760 static char *lp_string(const char *s)
1761 {
1762         char *ret;
1763         TALLOC_CTX *ctx = talloc_tos();
1764
1765         /* The follow debug is useful for tracking down memory problems
1766            especially if you have an inner loop that is calling a lp_*()
1767            function that returns a string.  Perhaps this debug should be
1768            present all the time? */
1769
1770 #if 0
1771         DEBUG(10, ("lp_string(%s)\n", s));
1772 #endif
1773
1774         ret = talloc_sub_basic(ctx,
1775                         get_current_username(),
1776                         current_user_info.domain,
1777                         s);
1778         if (trim_char(ret, '\"', '\"')) {
1779                 if (strchr(ret,'\"') != NULL) {
1780                         TALLOC_FREE(ret);
1781                         ret = talloc_sub_basic(ctx,
1782                                         get_current_username(),
1783                                         current_user_info.domain,
1784                                         s);
1785                 }
1786         }
1787         return ret;
1788 }
1789
1790 /*
1791    In this section all the functions that are used to access the 
1792    parameters from the rest of the program are defined 
1793 */
1794
1795 #define FN_GLOBAL_STRING(fn_name,ptr) \
1796  char *fn_name(void) {return(lp_string(*(char **)(ptr) ? *(char **)(ptr) : ""));}
1797 #define FN_GLOBAL_CONST_STRING(fn_name,ptr) \
1798  const char *fn_name(void) {return(*(const char **)(ptr) ? *(const char **)(ptr) : "");}
1799 #define FN_GLOBAL_LIST(fn_name,ptr) \
1800  const char **fn_name(void) {return(*(const char ***)(ptr));}
1801 #define FN_GLOBAL_BOOL(fn_name,ptr) \
1802  bool fn_name(void) {return(*(bool *)(ptr));}
1803 #define FN_GLOBAL_CHAR(fn_name,ptr) \
1804  char fn_name(void) {return(*(char *)(ptr));}
1805 #define FN_GLOBAL_INTEGER(fn_name,ptr) \
1806  int fn_name(void) {return(*(int *)(ptr));}
1807
1808 #define FN_LOCAL_STRING(fn_name,val) \
1809  char *fn_name(int i) {return(lp_string((LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val));}
1810 #define FN_LOCAL_CONST_STRING(fn_name,val) \
1811  const char *fn_name(int i) {return (const char *)((LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val);}
1812 #define FN_LOCAL_LIST(fn_name,val) \
1813  const char **fn_name(int i) {return(const char **)(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1814 #define FN_LOCAL_BOOL(fn_name,val) \
1815  bool fn_name(int i) {return(bool)(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1816 #define FN_LOCAL_INTEGER(fn_name,val) \
1817  int fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1818
1819 #define FN_LOCAL_PARM_BOOL(fn_name,val) \
1820  bool fn_name(const struct share_params *p) {return(bool)(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
1821 #define FN_LOCAL_PARM_INTEGER(fn_name,val) \
1822  int fn_name(const struct share_params *p) {return(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
1823 #define FN_LOCAL_PARM_STRING(fn_name,val) \
1824  char *fn_name(const struct share_params *p) {return(lp_string((LP_SNUM_OK(p->service) && ServicePtrs[(p->service)]->val) ? ServicePtrs[(p->service)]->val : sDefault.val));}
1825 #define FN_LOCAL_CHAR(fn_name,val) \
1826  char fn_name(const struct share_params *p) {return(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
1827
1828 FN_GLOBAL_STRING(lp_smb_ports, &Globals.smb_ports)
1829 FN_GLOBAL_STRING(lp_dos_charset, &Globals.dos_charset)
1830 FN_GLOBAL_STRING(lp_unix_charset, &Globals.unix_charset)
1831 FN_GLOBAL_STRING(lp_display_charset, &Globals.display_charset)
1832 FN_GLOBAL_STRING(lp_logfile, &Globals.szLogFile)
1833 FN_GLOBAL_STRING(lp_configfile, &Globals.szConfigFile)
1834 FN_GLOBAL_STRING(lp_smb_passwd_file, &Globals.szSMBPasswdFile)
1835 FN_GLOBAL_STRING(lp_private_dir, &Globals.szPrivateDir)
1836 FN_GLOBAL_STRING(lp_serverstring, &Globals.szServerString)
1837 FN_GLOBAL_INTEGER(lp_printcap_cache_time, &Globals.PrintcapCacheTime)
1838 FN_GLOBAL_STRING(lp_addport_cmd, &Globals.szAddPortCommand)
1839 FN_GLOBAL_STRING(lp_enumports_cmd, &Globals.szEnumPortsCommand)
1840 FN_GLOBAL_STRING(lp_addprinter_cmd, &Globals.szAddPrinterCommand)
1841 FN_GLOBAL_STRING(lp_deleteprinter_cmd, &Globals.szDeletePrinterCommand)
1842 FN_GLOBAL_STRING(lp_os2_driver_map, &Globals.szOs2DriverMap)
1843 FN_GLOBAL_STRING(lp_lockdir, &Globals.szLockDir)
1844 FN_GLOBAL_STRING(lp_piddir, &Globals.szPidDir)
1845 FN_GLOBAL_STRING(lp_mangling_method, &Globals.szManglingMethod)
1846 FN_GLOBAL_INTEGER(lp_mangle_prefix, &Globals.mangle_prefix)
1847 FN_GLOBAL_STRING(lp_utmpdir, &Globals.szUtmpDir)
1848 FN_GLOBAL_STRING(lp_wtmpdir, &Globals.szWtmpDir)
1849 FN_GLOBAL_BOOL(lp_utmp, &Globals.bUtmp)
1850 FN_GLOBAL_STRING(lp_rootdir, &Globals.szRootdir)
1851 FN_GLOBAL_STRING(lp_defaultservice, &Globals.szDefaultService)
1852 FN_GLOBAL_STRING(lp_msg_command, &Globals.szMsgCommand)
1853 FN_GLOBAL_STRING(lp_get_quota_command, &Globals.szGetQuota)
1854 FN_GLOBAL_STRING(lp_set_quota_command, &Globals.szSetQuota)
1855 FN_GLOBAL_STRING(lp_auto_services, &Globals.szAutoServices)
1856 FN_GLOBAL_STRING(lp_passwd_program, &Globals.szPasswdProgram)
1857 FN_GLOBAL_STRING(lp_passwd_chat, &Globals.szPasswdChat)
1858 FN_GLOBAL_STRING(lp_passwordserver, &Globals.szPasswordServer)
1859 FN_GLOBAL_STRING(lp_name_resolve_order, &Globals.szNameResolveOrder)
1860 FN_GLOBAL_STRING(lp_realm, &Globals.szRealm)
1861 FN_GLOBAL_CONST_STRING(lp_afs_username_map, &Globals.szAfsUsernameMap)
1862 FN_GLOBAL_INTEGER(lp_afs_token_lifetime, &Globals.iAfsTokenLifetime)
1863 FN_GLOBAL_STRING(lp_log_nt_token_command, &Globals.szLogNtTokenCommand)
1864 FN_GLOBAL_STRING(lp_username_map, &Globals.szUsernameMap)
1865 FN_GLOBAL_CONST_STRING(lp_logon_script, &Globals.szLogonScript)
1866 FN_GLOBAL_CONST_STRING(lp_logon_path, &Globals.szLogonPath)
1867 FN_GLOBAL_CONST_STRING(lp_logon_drive, &Globals.szLogonDrive)
1868 FN_GLOBAL_CONST_STRING(lp_logon_home, &Globals.szLogonHome)
1869 FN_GLOBAL_STRING(lp_remote_announce, &Globals.szRemoteAnnounce)
1870 FN_GLOBAL_STRING(lp_remote_browse_sync, &Globals.szRemoteBrowseSync)
1871 FN_GLOBAL_LIST(lp_wins_server_list, &Globals.szWINSservers)
1872 FN_GLOBAL_LIST(lp_interfaces, &Globals.szInterfaces)
1873 FN_GLOBAL_STRING(lp_socket_address, &Globals.szSocketAddress)
1874 FN_GLOBAL_STRING(lp_nis_home_map_name, &Globals.szNISHomeMapName)
1875 static FN_GLOBAL_STRING(lp_announce_version, &Globals.szAnnounceVersion)
1876 FN_GLOBAL_LIST(lp_netbios_aliases, &Globals.szNetbiosAliases)
1877 /* FN_GLOBAL_STRING(lp_passdb_backend, &Globals.szPassdbBackend)
1878  * lp_passdb_backend() should be replace by the this macro again after
1879  * some releases.
1880  * */
1881 const char *lp_passdb_backend(void)
1882 {
1883         char *delim, *quote;
1884
1885         delim = strchr( Globals.szPassdbBackend, ' ');
1886         /* no space at all */
1887         if (delim == NULL) {
1888                 goto out;
1889         }
1890
1891         quote = strchr(Globals.szPassdbBackend, '"');
1892         /* no quote char or non in the first part */
1893         if (quote == NULL || quote > delim) {
1894                 *delim = '\0';
1895                 goto warn;
1896         }
1897
1898         quote = strchr(quote+1, '"');
1899         if (quote == NULL) {
1900                 DEBUG(0, ("WARNING: Your 'passdb backend' configuration is invalid due to a missing second \" char.\n"));
1901                 goto out;
1902         } else if (*(quote+1) == '\0') {
1903                 /* space, fitting quote char, and one backend only */
1904                 goto out;
1905         } else {
1906                 /* terminate string after the fitting quote char */
1907                 *(quote+1) = '\0';
1908         }
1909
1910 warn:
1911         DEBUG(0, ("WARNING: Your 'passdb backend' configuration includes multiple backends.  This\n"
1912                 "is deprecated since Samba 3.0.23.  Please check WHATSNEW.txt or the section 'Passdb\n"
1913                 "Changes' from the ChangeNotes as part of the Samba HOWTO collection.  Only the first\n"
1914                 "backend (%s) is used.  The rest is ignored.\n", Globals.szPassdbBackend));
1915
1916 out:
1917         return Globals.szPassdbBackend;
1918 }
1919 FN_GLOBAL_LIST(lp_preload_modules, &Globals.szPreloadModules)
1920 FN_GLOBAL_STRING(lp_panic_action, &Globals.szPanicAction)
1921 FN_GLOBAL_STRING(lp_adduser_script, &Globals.szAddUserScript)
1922 FN_GLOBAL_STRING(lp_renameuser_script, &Globals.szRenameUserScript)
1923 FN_GLOBAL_STRING(lp_deluser_script, &Globals.szDelUserScript)
1924
1925 FN_GLOBAL_CONST_STRING(lp_guestaccount, &Globals.szGuestaccount)
1926 FN_GLOBAL_STRING(lp_addgroup_script, &Globals.szAddGroupScript)
1927 FN_GLOBAL_STRING(lp_delgroup_script, &Globals.szDelGroupScript)
1928 FN_GLOBAL_STRING(lp_addusertogroup_script, &Globals.szAddUserToGroupScript)
1929 FN_GLOBAL_STRING(lp_deluserfromgroup_script, &Globals.szDelUserFromGroupScript)
1930 FN_GLOBAL_STRING(lp_setprimarygroup_script, &Globals.szSetPrimaryGroupScript)
1931
1932 FN_GLOBAL_STRING(lp_addmachine_script, &Globals.szAddMachineScript)
1933
1934 FN_GLOBAL_STRING(lp_shutdown_script, &Globals.szShutdownScript)
1935 FN_GLOBAL_STRING(lp_abort_shutdown_script, &Globals.szAbortShutdownScript)
1936 FN_GLOBAL_STRING(lp_username_map_script, &Globals.szUsernameMapScript)
1937
1938 FN_GLOBAL_STRING(lp_check_password_script, &Globals.szCheckPasswordScript)
1939
1940 FN_GLOBAL_STRING(lp_wins_hook, &Globals.szWINSHook)
1941 FN_GLOBAL_CONST_STRING(lp_template_homedir, &Globals.szTemplateHomedir)
1942 FN_GLOBAL_CONST_STRING(lp_template_shell, &Globals.szTemplateShell)
1943 FN_GLOBAL_CONST_STRING(lp_winbind_separator, &Globals.szWinbindSeparator)
1944 FN_GLOBAL_INTEGER(lp_acl_compatibility, &Globals.iAclCompat)
1945 FN_GLOBAL_BOOL(lp_winbind_enum_users, &Globals.bWinbindEnumUsers)
1946 FN_GLOBAL_BOOL(lp_winbind_enum_groups, &Globals.bWinbindEnumGroups)
1947 FN_GLOBAL_BOOL(lp_winbind_use_default_domain, &Globals.bWinbindUseDefaultDomain)
1948 FN_GLOBAL_BOOL(lp_winbind_trusted_domains_only, &Globals.bWinbindTrustedDomainsOnly)
1949 FN_GLOBAL_BOOL(lp_winbind_nested_groups, &Globals.bWinbindNestedGroups)
1950 FN_GLOBAL_INTEGER(lp_winbind_expand_groups, &Globals.winbind_expand_groups)
1951 FN_GLOBAL_BOOL(lp_winbind_refresh_tickets, &Globals.bWinbindRefreshTickets)
1952 FN_GLOBAL_BOOL(lp_winbind_offline_logon, &Globals.bWinbindOfflineLogon)
1953 FN_GLOBAL_BOOL(lp_winbind_normalize_names, &Globals.bWinbindNormalizeNames)
1954 FN_GLOBAL_BOOL(lp_winbind_rpc_only, &Globals.bWinbindRpcOnly)
1955
1956 FN_GLOBAL_LIST(lp_idmap_domains, &Globals.szIdmapDomains)
1957 FN_GLOBAL_LIST(lp_idmap_backend, &Globals.szIdmapBackend) /* deprecated */
1958 FN_GLOBAL_STRING(lp_idmap_alloc_backend, &Globals.szIdmapAllocBackend)
1959 FN_GLOBAL_INTEGER(lp_idmap_cache_time, &Globals.iIdmapCacheTime)
1960 FN_GLOBAL_INTEGER(lp_idmap_negative_cache_time, &Globals.iIdmapNegativeCacheTime)
1961 FN_GLOBAL_INTEGER(lp_keepalive, &Globals.iKeepalive)
1962 FN_GLOBAL_BOOL(lp_passdb_expand_explicit, &Globals.bPassdbExpandExplicit)
1963
1964 FN_GLOBAL_STRING(lp_ldap_suffix, &Globals.szLdapSuffix)
1965 FN_GLOBAL_STRING(lp_ldap_admin_dn, &Globals.szLdapAdminDn)
1966 FN_GLOBAL_INTEGER(lp_ldap_ssl, &Globals.ldap_ssl)
1967 FN_GLOBAL_INTEGER(lp_ldap_passwd_sync, &Globals.ldap_passwd_sync)
1968 FN_GLOBAL_BOOL(lp_ldap_delete_dn, &Globals.ldap_delete_dn)
1969 FN_GLOBAL_INTEGER(lp_ldap_replication_sleep, &Globals.ldap_replication_sleep)
1970 FN_GLOBAL_INTEGER(lp_ldap_timeout, &Globals.ldap_timeout)
1971 FN_GLOBAL_INTEGER(lp_ldap_page_size, &Globals.ldap_page_size)
1972 FN_GLOBAL_INTEGER(lp_ldap_debug_level, &Globals.ldap_debug_level)
1973 FN_GLOBAL_INTEGER(lp_ldap_debug_threshold, &Globals.ldap_debug_threshold)
1974 FN_GLOBAL_STRING(lp_add_share_cmd, &Globals.szAddShareCommand)
1975 FN_GLOBAL_STRING(lp_change_share_cmd, &Globals.szChangeShareCommand)
1976 FN_GLOBAL_STRING(lp_delete_share_cmd, &Globals.szDeleteShareCommand)
1977 FN_GLOBAL_STRING(lp_usershare_path, &Globals.szUsersharePath)
1978 FN_GLOBAL_LIST(lp_usershare_prefix_allow_list, &Globals.szUsersharePrefixAllowList)
1979 FN_GLOBAL_LIST(lp_usershare_prefix_deny_list, &Globals.szUsersharePrefixDenyList)
1980
1981 FN_GLOBAL_LIST(lp_eventlog_list, &Globals.szEventLogs)
1982
1983 FN_GLOBAL_BOOL(lp_registry_shares, &Globals.bRegistryShares)
1984 FN_GLOBAL_BOOL(lp_usershare_allow_guests, &Globals.bUsershareAllowGuests)
1985 FN_GLOBAL_BOOL(lp_usershare_owner_only, &Globals.bUsershareOwnerOnly)
1986 FN_GLOBAL_BOOL(lp_disable_netbios, &Globals.bDisableNetbios)
1987 FN_GLOBAL_BOOL(lp_reset_on_zero_vc, &Globals.bResetOnZeroVC)
1988 FN_GLOBAL_BOOL(lp_ms_add_printer_wizard, &Globals.bMsAddPrinterWizard)
1989 FN_GLOBAL_BOOL(lp_dns_proxy, &Globals.bDNSproxy)
1990 FN_GLOBAL_BOOL(lp_wins_support, &Globals.bWINSsupport)
1991 FN_GLOBAL_BOOL(lp_we_are_a_wins_server, &Globals.bWINSsupport)
1992 FN_GLOBAL_BOOL(lp_wins_proxy, &Globals.bWINSproxy)
1993 FN_GLOBAL_BOOL(lp_local_master, &Globals.bLocalMaster)
1994 FN_GLOBAL_BOOL(lp_domain_logons, &Globals.bDomainLogons)
1995 FN_GLOBAL_BOOL(lp_load_printers, &Globals.bLoadPrinters)
1996 FN_GLOBAL_BOOL(lp_readraw, &Globals.bReadRaw)
1997 FN_GLOBAL_BOOL(lp_large_readwrite, &Globals.bLargeReadwrite)
1998 FN_GLOBAL_BOOL(lp_writeraw, &Globals.bWriteRaw)
1999 FN_GLOBAL_BOOL(lp_null_passwords, &Globals.bNullPasswords)
2000 FN_GLOBAL_BOOL(lp_obey_pam_restrictions, &Globals.bObeyPamRestrictions)
2001 FN_GLOBAL_BOOL(lp_encrypted_passwords, &Globals.bEncryptPasswords)
2002 FN_GLOBAL_BOOL(lp_update_encrypted, &Globals.bUpdateEncrypt)
2003 FN_GLOBAL_INTEGER(lp_client_schannel, &Globals.clientSchannel)
2004 FN_GLOBAL_INTEGER(lp_server_schannel, &Globals.serverSchannel)
2005 FN_GLOBAL_BOOL(lp_syslog_only, &Globals.bSyslogOnly)
2006 FN_GLOBAL_BOOL(lp_timestamp_logs, &Globals.bTimestampLogs)
2007 FN_GLOBAL_BOOL(lp_debug_prefix_timestamp, &Globals.bDebugPrefixTimestamp)
2008 FN_GLOBAL_BOOL(lp_debug_hires_timestamp, &Globals.bDebugHiresTimestamp)
2009 FN_GLOBAL_BOOL(lp_debug_pid, &Globals.bDebugPid)
2010 FN_GLOBAL_BOOL(lp_debug_uid, &Globals.bDebugUid)
2011 FN_GLOBAL_BOOL(lp_debug_class, &Globals.bDebugClass)
2012 FN_GLOBAL_BOOL(lp_enable_core_files, &Globals.bEnableCoreFiles)
2013 FN_GLOBAL_BOOL(lp_browse_list, &Globals.bBrowseList)
2014 FN_GLOBAL_BOOL(lp_nis_home_map, &Globals.bNISHomeMap)
2015 static FN_GLOBAL_BOOL(lp_time_server, &Globals.bTimeServer)
2016 FN_GLOBAL_BOOL(lp_bind_interfaces_only, &Globals.bBindInterfacesOnly)
2017 FN_GLOBAL_BOOL(lp_pam_password_change, &Globals.bPamPasswordChange)
2018 FN_GLOBAL_BOOL(lp_unix_password_sync, &Globals.bUnixPasswdSync)
2019 FN_GLOBAL_BOOL(lp_passwd_chat_debug, &Globals.bPasswdChatDebug)
2020 FN_GLOBAL_INTEGER(lp_passwd_chat_timeout, &Globals.iPasswdChatTimeout)
2021 FN_GLOBAL_BOOL(lp_nt_pipe_support, &Globals.bNTPipeSupport)
2022 FN_GLOBAL_BOOL(lp_nt_status_support, &Globals.bNTStatusSupport)
2023 FN_GLOBAL_BOOL(lp_stat_cache, &Globals.bStatCache)
2024 FN_GLOBAL_INTEGER(lp_max_stat_cache_size, &Globals.iMaxStatCacheSize)
2025 FN_GLOBAL_BOOL(lp_allow_trusted_domains, &Globals.bAllowTrustedDomains)
2026 FN_GLOBAL_INTEGER(lp_restrict_anonymous, &Globals.restrict_anonymous)
2027 FN_GLOBAL_BOOL(lp_lanman_auth, &Globals.bLanmanAuth)
2028 FN_GLOBAL_BOOL(lp_ntlm_auth, &Globals.bNTLMAuth)
2029 FN_GLOBAL_BOOL(lp_client_plaintext_auth, &Globals.bClientPlaintextAuth)
2030 FN_GLOBAL_BOOL(lp_client_lanman_auth, &Globals.bClientLanManAuth)
2031 FN_GLOBAL_BOOL(lp_client_ntlmv2_auth, &Globals.bClientNTLMv2Auth)
2032 FN_GLOBAL_BOOL(lp_host_msdfs, &Globals.bHostMSDfs)
2033 FN_GLOBAL_BOOL(lp_kernel_oplocks, &Globals.bKernelOplocks)
2034 FN_GLOBAL_BOOL(lp_enhanced_browsing, &Globals.enhanced_browsing)
2035 FN_GLOBAL_BOOL(lp_use_mmap, &Globals.bUseMmap)
2036 FN_GLOBAL_BOOL(lp_unix_extensions, &Globals.bUnixExtensions)
2037 FN_GLOBAL_BOOL(lp_use_spnego, &Globals.bUseSpnego)
2038 FN_GLOBAL_BOOL(lp_client_use_spnego, &Globals.bClientUseSpnego)
2039 FN_GLOBAL_BOOL(lp_hostname_lookups, &Globals.bHostnameLookups)
2040 FN_LOCAL_PARM_BOOL(lp_change_notify, bChangeNotify)
2041 FN_LOCAL_PARM_BOOL(lp_kernel_change_notify, bKernelChangeNotify)
2042 FN_GLOBAL_BOOL(lp_use_kerberos_keytab, &Globals.bUseKerberosKeytab)
2043 FN_GLOBAL_BOOL(lp_defer_sharing_violations, &Globals.bDeferSharingViolations)
2044 FN_GLOBAL_BOOL(lp_enable_privileges, &Globals.bEnablePrivileges)
2045 FN_GLOBAL_BOOL(lp_enable_asu_support, &Globals.bASUSupport)
2046 FN_GLOBAL_INTEGER(lp_os_level, &Globals.os_level)
2047 FN_GLOBAL_INTEGER(lp_max_ttl, &Globals.max_ttl)
2048 FN_GLOBAL_INTEGER(lp_max_wins_ttl, &Globals.max_wins_ttl)
2049 FN_GLOBAL_INTEGER(lp_min_wins_ttl, &Globals.min_wins_ttl)
2050 FN_GLOBAL_INTEGER(lp_max_log_size, &Globals.max_log_size)
2051 FN_GLOBAL_INTEGER(lp_max_open_files, &Globals.max_open_files)
2052 FN_GLOBAL_INTEGER(lp_open_files_db_hash_size, &Globals.open_files_db_hash_size)
2053 FN_GLOBAL_INTEGER(lp_maxxmit, &Globals.max_xmit)
2054 FN_GLOBAL_INTEGER(lp_maxmux, &Globals.max_mux)
2055 FN_GLOBAL_INTEGER(lp_passwordlevel, &Globals.pwordlevel)
2056 FN_GLOBAL_INTEGER(lp_usernamelevel, &Globals.unamelevel)
2057 FN_GLOBAL_INTEGER(lp_deadtime, &Globals.deadtime)
2058 FN_GLOBAL_BOOL(lp_getwd_cache, &Globals.getwd_cache)
2059 FN_GLOBAL_INTEGER(lp_maxprotocol, &Globals.maxprotocol)
2060 FN_GLOBAL_INTEGER(lp_minprotocol, &Globals.minprotocol)
2061 FN_GLOBAL_INTEGER(lp_security, &Globals.security)
2062 FN_GLOBAL_LIST(lp_auth_methods, &Globals.AuthMethods)
2063 FN_GLOBAL_BOOL(lp_paranoid_server_security, &Globals.paranoid_server_security)
2064 FN_GLOBAL_INTEGER(lp_maxdisksize, &Globals.maxdisksize)
2065 FN_GLOBAL_INTEGER(lp_lpqcachetime, &Globals.lpqcachetime)
2066 FN_GLOBAL_INTEGER(lp_max_smbd_processes, &Globals.iMaxSmbdProcesses)
2067 FN_GLOBAL_BOOL(_lp_disable_spoolss, &Globals.bDisableSpoolss)
2068 FN_GLOBAL_INTEGER(lp_syslog, &Globals.syslog)
2069 static FN_GLOBAL_INTEGER(lp_announce_as, &Globals.announce_as)
2070 FN_GLOBAL_INTEGER(lp_lm_announce, &Globals.lm_announce)
2071 FN_GLOBAL_INTEGER(lp_lm_interval, &Globals.lm_interval)
2072 FN_GLOBAL_INTEGER(lp_machine_password_timeout, &Globals.machine_password_timeout)
2073 FN_GLOBAL_INTEGER(lp_map_to_guest, &Globals.map_to_guest)
2074 FN_GLOBAL_INTEGER(lp_oplock_break_wait_time, &Globals.oplock_break_wait_time)
2075 FN_GLOBAL_INTEGER(lp_lock_spin_time, &Globals.iLockSpinTime)
2076 FN_GLOBAL_INTEGER(lp_usershare_max_shares, &Globals.iUsershareMaxShares)
2077 FN_GLOBAL_CONST_STRING(lp_socket_options, &Globals.szSocketOptions)
2078 FN_GLOBAL_INTEGER(lp_config_backend, &Globals.ConfigBackend);
2079
2080 FN_LOCAL_STRING(lp_preexec, szPreExec)
2081 FN_LOCAL_STRING(lp_postexec, szPostExec)
2082 FN_LOCAL_STRING(lp_rootpreexec, szRootPreExec)
2083 FN_LOCAL_STRING(lp_rootpostexec, szRootPostExec)
2084 FN_LOCAL_STRING(lp_servicename, szService)
2085 FN_LOCAL_CONST_STRING(lp_const_servicename, szService)
2086 FN_LOCAL_STRING(lp_pathname, szPath)
2087 FN_LOCAL_STRING(lp_dontdescend, szDontdescend)
2088 FN_LOCAL_STRING(lp_username, szUsername)
2089 FN_LOCAL_LIST(lp_invalid_users, szInvalidUsers)
2090 FN_LOCAL_LIST(lp_valid_users, szValidUsers)
2091 FN_LOCAL_LIST(lp_admin_users, szAdminUsers)
2092 FN_GLOBAL_LIST(lp_svcctl_list, &Globals.szServicesList)
2093 FN_LOCAL_STRING(lp_cups_options, szCupsOptions)
2094 FN_GLOBAL_STRING(lp_cups_server, &Globals.szCupsServer)
2095 FN_GLOBAL_STRING(lp_iprint_server, &Globals.szIPrintServer)
2096 FN_GLOBAL_CONST_STRING(lp_ctdbd_socket, &Globals.ctdbdSocket)
2097 FN_GLOBAL_LIST(lp_cluster_addresses, &Globals.szClusterAddresses)
2098 FN_GLOBAL_BOOL(lp_clustering, &Globals.clustering);
2099 FN_LOCAL_STRING(lp_printcommand, szPrintcommand)
2100 FN_LOCAL_STRING(lp_lpqcommand, szLpqcommand)
2101 FN_LOCAL_STRING(lp_lprmcommand, szLprmcommand)
2102 FN_LOCAL_STRING(lp_lppausecommand, szLppausecommand)
2103 FN_LOCAL_STRING(lp_lpresumecommand, szLpresumecommand)
2104 FN_LOCAL_STRING(lp_queuepausecommand, szQueuepausecommand)
2105 FN_LOCAL_STRING(lp_queueresumecommand, szQueueresumecommand)
2106 static FN_LOCAL_STRING(_lp_printername, szPrintername)
2107 FN_LOCAL_CONST_STRING(lp_printjob_username, szPrintjobUsername)
2108 FN_LOCAL_LIST(lp_hostsallow, szHostsallow)
2109 FN_LOCAL_LIST(lp_hostsdeny, szHostsdeny)
2110 FN_LOCAL_STRING(lp_magicscript, szMagicScript)
2111 FN_LOCAL_STRING(lp_magicoutput, szMagicOutput)
2112 FN_LOCAL_STRING(lp_comment, comment)
2113 FN_LOCAL_STRING(lp_force_user, force_user)
2114 FN_LOCAL_STRING(lp_force_group, force_group)
2115 FN_LOCAL_LIST(lp_readlist, readlist)
2116 FN_LOCAL_LIST(lp_writelist, writelist)
2117 FN_LOCAL_LIST(lp_printer_admin, printer_admin)
2118 FN_LOCAL_STRING(lp_fstype, fstype)
2119 FN_LOCAL_LIST(lp_vfs_objects, szVfsObjects)
2120 FN_LOCAL_STRING(lp_msdfs_proxy, szMSDfsProxy)
2121 static FN_LOCAL_STRING(lp_volume, volume)
2122 FN_LOCAL_STRING(lp_veto_files, szVetoFiles)
2123 FN_LOCAL_STRING(lp_hide_files, szHideFiles)
2124 FN_LOCAL_STRING(lp_veto_oplocks, szVetoOplockFiles)
2125 FN_LOCAL_BOOL(lp_msdfs_root, bMSDfsRoot)
2126 FN_LOCAL_STRING(lp_aio_write_behind, szAioWriteBehind)
2127 FN_LOCAL_STRING(lp_dfree_command, szDfree)
2128 FN_LOCAL_BOOL(lp_autoloaded, autoloaded)
2129 FN_LOCAL_BOOL(lp_preexec_close, bPreexecClose)
2130 FN_LOCAL_BOOL(lp_rootpreexec_close, bRootpreexecClose)
2131 FN_LOCAL_INTEGER(lp_casesensitive, iCaseSensitive)
2132 FN_LOCAL_BOOL(lp_preservecase, bCasePreserve)
2133 FN_LOCAL_BOOL(lp_shortpreservecase, bShortCasePreserve)
2134 FN_LOCAL_BOOL(lp_hide_dot_files, bHideDotFiles)
2135 FN_LOCAL_BOOL(lp_hide_special_files, bHideSpecialFiles)
2136 FN_LOCAL_BOOL(lp_hideunreadable, bHideUnReadable)
2137 FN_LOCAL_BOOL(lp_hideunwriteable_files, bHideUnWriteableFiles)
2138 FN_LOCAL_BOOL(lp_browseable, bBrowseable)
2139 FN_LOCAL_BOOL(lp_readonly, bRead_only)
2140 FN_LOCAL_BOOL(lp_no_set_dir, bNo_set_dir)
2141 FN_LOCAL_BOOL(lp_guest_ok, bGuest_ok)
2142 FN_LOCAL_BOOL(lp_guest_only, bGuest_only)
2143 FN_LOCAL_BOOL(lp_hidden, bHidden)
2144 FN_LOCAL_BOOL(lp_print_ok, bPrint_ok)
2145 FN_LOCAL_BOOL(lp_map_hidden, bMap_hidden)
2146 FN_LOCAL_BOOL(lp_map_archive, bMap_archive)
2147 FN_LOCAL_BOOL(lp_store_dos_attributes, bStoreDosAttributes)
2148 FN_LOCAL_BOOL(lp_dmapi_support, bDmapiSupport)
2149 FN_LOCAL_PARM_BOOL(lp_locking, bLocking)
2150 FN_LOCAL_PARM_INTEGER(lp_strict_locking, iStrictLocking)
2151 FN_LOCAL_PARM_BOOL(lp_posix_locking, bPosixLocking)
2152 FN_LOCAL_BOOL(lp_share_modes, bShareModes)
2153 FN_LOCAL_BOOL(lp_oplocks, bOpLocks)
2154 FN_LOCAL_BOOL(lp_level2_oplocks, bLevel2OpLocks)
2155 FN_LOCAL_BOOL(lp_onlyuser, bOnlyUser)
2156 FN_LOCAL_PARM_BOOL(lp_manglednames, bMangledNames)
2157 FN_LOCAL_BOOL(lp_widelinks, bWidelinks)
2158 FN_LOCAL_BOOL(lp_symlinks, bSymlinks)
2159 FN_LOCAL_BOOL(lp_syncalways, bSyncAlways)
2160 FN_LOCAL_BOOL(lp_strict_allocate, bStrictAllocate)
2161 FN_LOCAL_BOOL(lp_strict_sync, bStrictSync)
2162 FN_LOCAL_BOOL(lp_map_system, bMap_system)
2163 FN_LOCAL_BOOL(lp_delete_readonly, bDeleteReadonly)
2164 FN_LOCAL_BOOL(lp_fake_oplocks, bFakeOplocks)
2165 FN_LOCAL_BOOL(lp_recursive_veto_delete, bDeleteVetoFiles)
2166 FN_LOCAL_BOOL(lp_dos_filemode, bDosFilemode)
2167 FN_LOCAL_BOOL(lp_dos_filetimes, bDosFiletimes)
2168 FN_LOCAL_BOOL(lp_dos_filetime_resolution, bDosFiletimeResolution)
2169 FN_LOCAL_BOOL(lp_fake_dir_create_times, bFakeDirCreateTimes)
2170 FN_LOCAL_BOOL(lp_blocking_locks, bBlockingLocks)
2171 FN_LOCAL_BOOL(lp_inherit_perms, bInheritPerms)
2172 FN_LOCAL_BOOL(lp_inherit_acls, bInheritACLS)
2173 FN_LOCAL_BOOL(lp_inherit_owner, bInheritOwner)
2174 FN_LOCAL_BOOL(lp_use_client_driver, bUseClientDriver)
2175 FN_LOCAL_BOOL(lp_default_devmode, bDefaultDevmode)
2176 FN_LOCAL_BOOL(lp_force_printername, bForcePrintername)
2177 FN_LOCAL_BOOL(lp_nt_acl_support, bNTAclSupport)
2178 FN_LOCAL_BOOL(lp_force_unknown_acl_user, bForceUnknownAclUser)
2179 FN_LOCAL_BOOL(lp_ea_support, bEASupport)
2180 FN_LOCAL_BOOL(_lp_use_sendfile, bUseSendfile)
2181 FN_LOCAL_BOOL(lp_profile_acls, bProfileAcls)
2182 FN_LOCAL_BOOL(lp_map_acl_inherit, bMap_acl_inherit)
2183 FN_LOCAL_BOOL(lp_afs_share, bAfs_Share)
2184 FN_LOCAL_BOOL(lp_acl_check_permissions, bAclCheckPermissions)
2185 FN_LOCAL_BOOL(lp_acl_group_control, bAclGroupControl)
2186 FN_LOCAL_BOOL(lp_acl_map_full_control, bAclMapFullControl)
2187 FN_LOCAL_INTEGER(lp_create_mask, iCreate_mask)
2188 FN_LOCAL_INTEGER(lp_force_create_mode, iCreate_force_mode)
2189 FN_LOCAL_INTEGER(lp_security_mask, iSecurity_mask)
2190 FN_LOCAL_INTEGER(lp_force_security_mode, iSecurity_force_mode)
2191 FN_LOCAL_INTEGER(lp_dir_mask, iDir_mask)
2192 FN_LOCAL_INTEGER(lp_force_dir_mode, iDir_force_mode)
2193 FN_LOCAL_INTEGER(lp_dir_security_mask, iDir_Security_mask)
2194 FN_LOCAL_INTEGER(lp_force_dir_security_mode, iDir_Security_force_mode)
2195 FN_LOCAL_INTEGER(lp_max_connections, iMaxConnections)
2196 FN_LOCAL_INTEGER(lp_defaultcase, iDefaultCase)
2197 FN_LOCAL_INTEGER(lp_minprintspace, iMinPrintSpace)
2198 FN_LOCAL_INTEGER(lp_printing, iPrinting)
2199 FN_LOCAL_INTEGER(lp_max_reported_jobs, iMaxReportedPrintJobs)
2200 FN_LOCAL_INTEGER(lp_oplock_contention_limit, iOplockContentionLimit)
2201 FN_LOCAL_INTEGER(lp_csc_policy, iCSCPolicy)
2202 FN_LOCAL_INTEGER(lp_write_cache_size, iWriteCacheSize)
2203 FN_LOCAL_INTEGER(lp_block_size, iBlock_size)
2204 FN_LOCAL_INTEGER(lp_dfree_cache_time, iDfreeCacheTime)
2205 FN_LOCAL_INTEGER(lp_allocation_roundup_size, iallocation_roundup_size)
2206 FN_LOCAL_INTEGER(lp_aio_read_size, iAioReadSize)
2207 FN_LOCAL_INTEGER(lp_aio_write_size, iAioWriteSize)
2208 FN_LOCAL_INTEGER(lp_map_readonly, iMap_readonly)
2209 FN_LOCAL_INTEGER(lp_directory_name_cache_size, iDirectoryNameCacheSize)
2210 FN_LOCAL_INTEGER(lp_smb_encrypt, ismb_encrypt)
2211 FN_LOCAL_CHAR(lp_magicchar, magic_char)
2212 FN_GLOBAL_INTEGER(lp_winbind_cache_time, &Globals.winbind_cache_time)
2213 FN_GLOBAL_LIST(lp_winbind_nss_info, &Globals.szWinbindNssInfo)
2214 FN_GLOBAL_INTEGER(lp_algorithmic_rid_base, &Globals.AlgorithmicRidBase)
2215 FN_GLOBAL_INTEGER(lp_name_cache_timeout, &Globals.name_cache_timeout)
2216 FN_GLOBAL_INTEGER(lp_client_signing, &Globals.client_signing)
2217 FN_GLOBAL_INTEGER(lp_server_signing, &Globals.server_signing)
2218 FN_GLOBAL_INTEGER(lp_client_ldap_sasl_wrapping, &Globals.client_ldap_sasl_wrapping)
2219
2220 /* local prototypes */
2221
2222 static int map_parameter(const char *pszParmName);
2223 static int map_parameter_canonical(const char *pszParmName, bool *inverse);
2224 static bool set_boolean(bool *pb, const char *pszParmValue);
2225 static const char *get_boolean(bool bool_value);
2226 static int getservicebyname(const char *pszServiceName,
2227                             service * pserviceDest);
2228 static void copy_service(service * pserviceDest,
2229                          service * pserviceSource,
2230                          struct bitmap *pcopymapDest);
2231 static bool do_parameter(const char *pszParmName, const char *pszParmValue);
2232 static bool do_section(const char *pszSectionName);
2233 static void init_copymap(service * pservice);
2234 static bool hash_a_service(const char *name, int number);
2235 static void free_service_byindex(int iService);
2236 static char * canonicalize_servicename(const char *name);
2237 static void show_parameter(int parmIndex);
2238 static bool is_synonym_of(int parm1, int parm2, bool *inverse);
2239
2240 /* This is a helper function for parametrical options support. */
2241 /* It returns a pointer to parametrical option value if it exists or NULL otherwise */
2242 /* Actual parametrical functions are quite simple */
2243 static param_opt_struct *get_parametrics(int snum, const char *type, const char *option)
2244 {
2245         bool global_section = False;
2246         char* param_key;
2247         param_opt_struct *data;
2248         
2249         if (snum >= iNumServices) return NULL;
2250         
2251         if (snum < 0) { 
2252                 data = Globals.param_opt;
2253                 global_section = True;
2254         } else {
2255                 data = ServicePtrs[snum]->param_opt;
2256         }
2257     
2258         if (asprintf(&param_key, "%s:%s", type, option) == -1) {
2259                 DEBUG(0,("asprintf failed!\n"));
2260                 return NULL;
2261         }
2262
2263         while (data) {
2264                 if (strcmp(data->key, param_key) == 0) {
2265                         string_free(&param_key);
2266                         return data;
2267                 }
2268                 data = data->next;
2269         }
2270
2271         if (!global_section) {
2272                 /* Try to fetch the same option but from globals */
2273                 /* but only if we are not already working with Globals */
2274                 data = Globals.param_opt;
2275                 while (data) {
2276                         if (strcmp(data->key, param_key) == 0) {
2277                                 string_free(&param_key);
2278                                 return data;
2279                         }
2280                         data = data->next;
2281                 }
2282         }
2283
2284         string_free(&param_key);
2285         
2286         return NULL;
2287 }
2288
2289
2290 #define MISSING_PARAMETER(name) \
2291     DEBUG(0, ("%s(): value is NULL or empty!\n", #name))
2292
2293 /*******************************************************************
2294 convenience routine to return int parameters.
2295 ********************************************************************/
2296 static int lp_int(const char *s)
2297 {
2298
2299         if (!s || !*s) {
2300                 MISSING_PARAMETER(lp_int);
2301                 return (-1);
2302         }
2303
2304         return (int)strtol(s, NULL, 0);
2305 }
2306
2307 /*******************************************************************
2308 convenience routine to return unsigned long parameters.
2309 ********************************************************************/
2310 static unsigned long lp_ulong(const char *s)
2311 {
2312
2313         if (!s || !*s) {
2314                 MISSING_PARAMETER(lp_ulong);
2315                 return (0);
2316         }
2317
2318         return strtoul(s, NULL, 0);
2319 }
2320
2321 /*******************************************************************
2322 convenience routine to return boolean parameters.
2323 ********************************************************************/
2324 static bool lp_bool(const char *s)
2325 {
2326         bool ret = False;
2327
2328         if (!s || !*s) {
2329                 MISSING_PARAMETER(lp_bool);
2330                 return False;
2331         }
2332         
2333         if (!set_boolean(&ret,s)) {
2334                 DEBUG(0,("lp_bool(%s): value is not boolean!\n",s));
2335                 return False;
2336         }
2337
2338         return ret;
2339 }
2340
2341 /*******************************************************************
2342 convenience routine to return enum parameters.
2343 ********************************************************************/
2344 static int lp_enum(const char *s,const struct enum_list *_enum)
2345 {
2346         int i;
2347
2348         if (!s || !*s || !_enum) {
2349                 MISSING_PARAMETER(lp_enum);
2350                 return (-1);
2351         }
2352         
2353         for (i=0; _enum[i].name; i++) {
2354                 if (strequal(_enum[i].name,s))
2355                         return _enum[i].value;
2356         }
2357
2358         DEBUG(0,("lp_enum(%s,enum): value is not in enum_list!\n",s));
2359         return (-1);
2360 }
2361
2362 #undef MISSING_PARAMETER
2363
2364 /* DO NOT USE lp_parm_string ANYMORE!!!!
2365  * use lp_parm_const_string or lp_parm_talloc_string
2366  *
2367  * lp_parm_string is only used to let old modules find this symbol
2368  */
2369 #undef lp_parm_string
2370  char *lp_parm_string(const char *servicename, const char *type, const char *option);
2371  char *lp_parm_string(const char *servicename, const char *type, const char *option)
2372 {
2373         return lp_parm_talloc_string(lp_servicenumber(servicename), type, option, NULL);
2374 }
2375
2376 /* Return parametric option from a given service. Type is a part of option before ':' */
2377 /* Parametric option has following syntax: 'Type: option = value' */
2378 /* the returned value is talloced on the talloc_tos() */
2379 char *lp_parm_talloc_string(int snum, const char *type, const char *option, const char *def)
2380 {
2381         param_opt_struct *data = get_parametrics(snum, type, option);
2382         
2383         if (data == NULL||data->value==NULL) {
2384                 if (def) {
2385                         return lp_string(def);
2386                 } else {
2387                         return NULL;
2388                 }
2389         }
2390
2391         return lp_string(data->value);
2392 }
2393
2394 /* Return parametric option from a given service. Type is a part of option before ':' */
2395 /* Parametric option has following syntax: 'Type: option = value' */
2396 const char *lp_parm_const_string(int snum, const char *type, const char *option, const char *def)
2397 {
2398         param_opt_struct *data = get_parametrics(snum, type, option);
2399         
2400         if (data == NULL||data->value==NULL)
2401                 return def;
2402                 
2403         return data->value;
2404 }
2405
2406 /* Return parametric option from a given service. Type is a part of option before ':' */
2407 /* Parametric option has following syntax: 'Type: option = value' */
2408
2409 const char **lp_parm_string_list(int snum, const char *type, const char *option, const char **def)
2410 {
2411         param_opt_struct *data = get_parametrics(snum, type, option);
2412
2413         if (data == NULL||data->value==NULL)
2414                 return (const char **)def;
2415                 
2416         if (data->list==NULL) {
2417                 data->list = str_list_make(NULL, data->value, NULL);
2418         }
2419
2420         return (const char **)data->list;
2421 }
2422
2423 /* Return parametric option from a given service. Type is a part of option before ':' */
2424 /* Parametric option has following syntax: 'Type: option = value' */
2425
2426 int lp_parm_int(int snum, const char *type, const char *option, int def)
2427 {
2428         param_opt_struct *data = get_parametrics(snum, type, option);
2429         
2430         if (data && data->value && *data->value)
2431                 return lp_int(data->value);
2432
2433         return def;
2434 }
2435
2436 /* Return parametric option from a given service. Type is a part of option before ':' */
2437 /* Parametric option has following syntax: 'Type: option = value' */
2438
2439 unsigned long lp_parm_ulong(int snum, const char *type, const char *option, unsigned long def)
2440 {
2441         param_opt_struct *data = get_parametrics(snum, type, option);
2442         
2443         if (data && data->value && *data->value)
2444                 return lp_ulong(data->value);
2445
2446         return def;
2447 }
2448
2449 /* Return parametric option from a given service. Type is a part of option before ':' */
2450 /* Parametric option has following syntax: 'Type: option = value' */
2451
2452 bool lp_parm_bool(int snum, const char *type, const char *option, bool def)
2453 {
2454         param_opt_struct *data = get_parametrics(snum, type, option);
2455         
2456         if (data && data->value && *data->value)
2457                 return lp_bool(data->value);
2458
2459         return def;
2460 }
2461
2462 /* Return parametric option from a given service. Type is a part of option before ':' */
2463 /* Parametric option has following syntax: 'Type: option = value' */
2464
2465 int lp_parm_enum(int snum, const char *type, const char *option,
2466                  const struct enum_list *_enum, int def)
2467 {
2468         param_opt_struct *data = get_parametrics(snum, type, option);
2469         
2470         if (data && data->value && *data->value && _enum)
2471                 return lp_enum(data->value, _enum);
2472
2473         return def;
2474 }
2475
2476
2477 /***************************************************************************
2478  Initialise a service to the defaults.
2479 ***************************************************************************/
2480
2481 static void init_service(service * pservice)
2482 {
2483         memset((char *)pservice, '\0', sizeof(service));
2484         copy_service(pservice, &sDefault, NULL);
2485 }
2486
2487 /***************************************************************************
2488  Free the dynamically allocated parts of a service struct.
2489 ***************************************************************************/
2490
2491 static void free_service(service *pservice)
2492 {
2493         int i;
2494         param_opt_struct *data, *pdata;
2495         if (!pservice)
2496                 return;
2497
2498         if (pservice->szService)
2499                 DEBUG(5, ("free_service: Freeing service %s\n",
2500                        pservice->szService));
2501
2502         string_free(&pservice->szService);
2503         bitmap_free(pservice->copymap);
2504
2505         for (i = 0; parm_table[i].label; i++) {
2506                 if ((parm_table[i].type == P_STRING ||
2507                      parm_table[i].type == P_USTRING) &&
2508                     parm_table[i].p_class == P_LOCAL)
2509                         string_free((char **)
2510                                     (((char *)pservice) +
2511                                      PTR_DIFF(parm_table[i].ptr, &sDefault)));
2512                 else if (parm_table[i].type == P_LIST &&
2513                          parm_table[i].p_class == P_LOCAL)
2514                              TALLOC_FREE(*((char ***)
2515                                            (((char *)pservice) +
2516                                             PTR_DIFF(parm_table[i].ptr,
2517                                                      &sDefault))));
2518         }
2519
2520         data = pservice->param_opt;
2521         if (data)
2522                 DEBUG(5,("Freeing parametrics:\n"));
2523         while (data) {
2524                 DEBUG(5,("[%s = %s]\n", data->key, data->value));
2525                 string_free(&data->key);
2526                 string_free(&data->value);
2527                 TALLOC_FREE(data->list);
2528                 pdata = data->next;
2529                 SAFE_FREE(data);
2530                 data = pdata;
2531         }
2532
2533         ZERO_STRUCTP(pservice);
2534 }
2535
2536
2537 /***************************************************************************
2538  remove a service indexed in the ServicePtrs array from the ServiceHash
2539  and free the dynamically allocated parts
2540 ***************************************************************************/
2541
2542 static void free_service_byindex(int idx)
2543 {
2544         if ( !LP_SNUM_OK(idx) ) 
2545                 return;
2546
2547         ServicePtrs[idx]->valid = False;
2548         invalid_services[num_invalid_services++] = idx;
2549
2550         /* we have to cleanup the hash record */
2551
2552         if (ServicePtrs[idx]->szService) {
2553                 char *canon_name = canonicalize_servicename(
2554                         ServicePtrs[idx]->szService );
2555                 
2556                 dbwrap_delete_bystring(ServiceHash, canon_name );
2557                 TALLOC_FREE(canon_name);
2558         }
2559
2560         free_service(ServicePtrs[idx]);
2561 }
2562
2563 /***************************************************************************
2564  Add a new service to the services array initialising it with the given 
2565  service. 
2566 ***************************************************************************/
2567
2568 static int add_a_service(const service *pservice, const char *name)
2569 {
2570         int i;
2571         service tservice;
2572         int num_to_alloc = iNumServices + 1;
2573         param_opt_struct *data, *pdata;
2574
2575         tservice = *pservice;
2576
2577         /* it might already exist */
2578         if (name) {
2579                 i = getservicebyname(name, NULL);
2580                 if (i >= 0) {
2581                         /* Clean all parametric options for service */
2582                         /* They will be added during parsing again */
2583                         data = ServicePtrs[i]->param_opt;
2584                         while (data) {
2585                                 string_free(&data->key);
2586                                 string_free(&data->value);
2587                                 TALLOC_FREE(data->list);
2588                                 pdata = data->next;
2589                                 SAFE_FREE(data);
2590                                 data = pdata;
2591                         }
2592                         ServicePtrs[i]->param_opt = NULL;
2593                         return (i);
2594                 }
2595         }
2596
2597         /* find an invalid one */
2598         i = iNumServices;
2599         if (num_invalid_services > 0) {
2600                 i = invalid_services[--num_invalid_services];
2601         }
2602
2603         /* if not, then create one */
2604         if (i == iNumServices) {
2605                 service **tsp;
2606                 int *tinvalid;
2607                 
2608                 tsp = SMB_REALLOC_ARRAY_KEEP_OLD_ON_ERROR(ServicePtrs, service *, num_to_alloc);
2609                 if (tsp == NULL) {
2610                         DEBUG(0,("add_a_service: failed to enlarge ServicePtrs!\n"));
2611                         return (-1);
2612                 }
2613                 ServicePtrs = tsp;
2614                 ServicePtrs[iNumServices] = SMB_MALLOC_P(service);
2615                 if (!ServicePtrs[iNumServices]) {
2616                         DEBUG(0,("add_a_service: out of memory!\n"));
2617                         return (-1);
2618                 }
2619                 iNumServices++;
2620
2621                 /* enlarge invalid_services here for now... */
2622                 tinvalid = SMB_REALLOC_ARRAY_KEEP_OLD_ON_ERROR(invalid_services, int,
2623                                              num_to_alloc);
2624                 if (tinvalid == NULL) {
2625                         DEBUG(0,("add_a_service: failed to enlarge "
2626                                  "invalid_services!\n"));
2627                         return (-1);
2628                 }
2629                 invalid_services = tinvalid;
2630         } else {
2631                 free_service_byindex(i);
2632         }
2633
2634         ServicePtrs[i]->valid = True;
2635
2636         init_service(ServicePtrs[i]);
2637         copy_service(ServicePtrs[i], &tservice, NULL);
2638         if (name)
2639                 string_set(&ServicePtrs[i]->szService, name);
2640                 
2641         DEBUG(8,("add_a_service: Creating snum = %d for %s\n", 
2642                 i, ServicePtrs[i]->szService));
2643
2644         if (!hash_a_service(ServicePtrs[i]->szService, i)) {
2645                 return (-1);
2646         }
2647                 
2648         return (i);
2649 }
2650
2651 /***************************************************************************
2652   Convert a string to uppercase and remove whitespaces.
2653 ***************************************************************************/
2654
2655 static char *canonicalize_servicename(const char *src)
2656 {
2657         char *result;
2658
2659         if ( !src ) {
2660                 DEBUG(0,("canonicalize_servicename: NULL source name!\n"));
2661                 return NULL;
2662         }
2663
2664         result = talloc_strdup(talloc_tos(), src);
2665         SMB_ASSERT(result != NULL);
2666
2667         strlower_m(result);
2668         return result;
2669 }
2670
2671 /***************************************************************************
2672   Add a name/index pair for the services array to the hash table.
2673 ***************************************************************************/
2674
2675 static bool hash_a_service(const char *name, int idx)
2676 {
2677         char *canon_name;
2678
2679         if ( !ServiceHash ) {
2680                 DEBUG(10,("hash_a_service: creating servicehash\n"));
2681                 ServiceHash = db_open_rbt(NULL);
2682                 if ( !ServiceHash ) {
2683                         DEBUG(0,("hash_a_service: open tdb servicehash failed!\n"));
2684                         return False;
2685                 }
2686         }
2687
2688         DEBUG(10,("hash_a_service: hashing index %d for service name %s\n",
2689                 idx, name));
2690
2691         canon_name = canonicalize_servicename( name );
2692
2693         dbwrap_store_bystring(ServiceHash, canon_name,
2694                               make_tdb_data((uint8 *)&idx, sizeof(idx)),
2695                               TDB_REPLACE);
2696
2697         TALLOC_FREE(canon_name);
2698
2699         return True;
2700 }
2701
2702 /***************************************************************************
2703  Add a new home service, with the specified home directory, defaults coming
2704  from service ifrom.
2705 ***************************************************************************/
2706
2707 bool lp_add_home(const char *pszHomename, int iDefaultService,
2708                  const char *user, const char *pszHomedir)
2709 {
2710         int i;
2711
2712         i = add_a_service(ServicePtrs[iDefaultService], pszHomename);
2713
2714         if (i < 0)
2715                 return (False);
2716
2717         if (!(*(ServicePtrs[iDefaultService]->szPath))
2718             || strequal(ServicePtrs[iDefaultService]->szPath, lp_pathname(GLOBAL_SECTION_SNUM))) {
2719                 string_set(&ServicePtrs[i]->szPath, pszHomedir);
2720         }
2721
2722         if (!(*(ServicePtrs[i]->comment))) {
2723                 char *comment = NULL;
2724                 if (asprintf(&comment, "Home directory of %s", user) < 0) {
2725                         return false;
2726                 }
2727                 string_set(&ServicePtrs[i]->comment, comment);
2728                 SAFE_FREE(comment);
2729         }
2730
2731         /* set the browseable flag from the global default */
2732
2733         ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
2734
2735         ServicePtrs[i]->autoloaded = True;
2736
2737         DEBUG(3, ("adding home's share [%s] for user '%s' at '%s'\n", pszHomename, 
2738                user, ServicePtrs[i]->szPath ));
2739
2740         return (True);
2741 }
2742
2743 /***************************************************************************
2744  Add a new service, based on an old one.
2745 ***************************************************************************/
2746
2747 int lp_add_service(const char *pszService, int iDefaultService)
2748 {
2749         if (iDefaultService < 0) {
2750                 return add_a_service(&sDefault, pszService);
2751         }
2752
2753         return (add_a_service(ServicePtrs[iDefaultService], pszService));
2754 }
2755
2756 /***************************************************************************
2757  Add the IPC service.
2758 ***************************************************************************/
2759
2760 static bool lp_add_ipc(const char *ipc_name, bool guest_ok)
2761 {
2762         char *comment = NULL;
2763         int i = add_a_service(&sDefault, ipc_name);
2764
2765         if (i < 0)
2766                 return (False);
2767
2768         if (asprintf(&comment, "IPC Service (%s)",
2769                                 Globals.szServerString) < 0) {
2770                 return (False);
2771         }
2772
2773         string_set(&ServicePtrs[i]->szPath, tmpdir());
2774         string_set(&ServicePtrs[i]->szUsername, "");
2775         string_set(&ServicePtrs[i]->comment, comment);
2776         string_set(&ServicePtrs[i]->fstype, "IPC");
2777         ServicePtrs[i]->iMaxConnections = 0;
2778         ServicePtrs[i]->bAvailable = True;
2779         ServicePtrs[i]->bRead_only = True;
2780         ServicePtrs[i]->bGuest_only = False;
2781         ServicePtrs[i]->bHidden = True;
2782         ServicePtrs[i]->bGuest_ok = guest_ok;
2783         ServicePtrs[i]->bPrint_ok = False;
2784         ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
2785
2786         DEBUG(3, ("adding IPC service\n"));
2787
2788         SAFE_FREE(comment);
2789         return (True);
2790 }
2791
2792 /***************************************************************************
2793  Add a new printer service, with defaults coming from service iFrom.
2794 ***************************************************************************/
2795
2796 bool lp_add_printer(const char *pszPrintername, int iDefaultService)
2797 {
2798         const char *comment = "From Printcap";
2799         int i = add_a_service(ServicePtrs[iDefaultService], pszPrintername);
2800
2801         if (i < 0)
2802                 return (False);
2803
2804         /* note that we do NOT default the availability flag to True - */
2805         /* we take it from the default service passed. This allows all */
2806         /* dynamic printers to be disabled by disabling the [printers] */
2807         /* entry (if/when the 'available' keyword is implemented!).    */
2808
2809         /* the printer name is set to the service name. */
2810         string_set(&ServicePtrs[i]->szPrintername, pszPrintername);
2811         string_set(&ServicePtrs[i]->comment, comment);
2812
2813         /* set the browseable flag from the gloabl default */
2814         ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
2815
2816         /* Printers cannot be read_only. */
2817         ServicePtrs[i]->bRead_only = False;
2818         /* No share modes on printer services. */
2819         ServicePtrs[i]->bShareModes = False;
2820         /* No oplocks on printer services. */
2821         ServicePtrs[i]->bOpLocks = False;
2822         /* Printer services must be printable. */
2823         ServicePtrs[i]->bPrint_ok = True;
2824         
2825         DEBUG(3, ("adding printer service %s\n", pszPrintername));
2826
2827         return (True);
2828 }
2829
2830
2831 /***************************************************************************
2832  Check whether the given parameter name is valid.
2833  Parametric options (names containing a colon) are considered valid.
2834 ***************************************************************************/
2835
2836 bool lp_parameter_is_valid(const char *pszParmName)
2837 {
2838         return ((map_parameter(pszParmName) != -1) ||
2839                 (strchr(pszParmName, ':') != NULL));
2840 }
2841
2842 /***************************************************************************
2843  Check whether the given name is the name of a global parameter.
2844  Returns True for strings belonging to parameters of class
2845  P_GLOBAL, False for all other strings, also for parametric options
2846  and strings not belonging to any option.
2847 ***************************************************************************/
2848
2849 bool lp_parameter_is_global(const char *pszParmName)
2850 {
2851         int num = map_parameter(pszParmName);
2852
2853         if (num >= 0) {
2854                 return (parm_table[num].p_class == P_GLOBAL);
2855         }
2856
2857         return False;
2858 }
2859
2860 /**************************************************************************
2861  Check whether the given name is the canonical name of a parameter.
2862  Returns False if it is not a valid parameter Name.
2863  For parametric options, True is returned.
2864 **************************************************************************/
2865
2866 bool lp_parameter_is_canonical(const char *parm_name)
2867 {
2868         if (!lp_parameter_is_valid(parm_name)) {
2869                 return False;
2870         }
2871
2872         return (map_parameter(parm_name) ==
2873                 map_parameter_canonical(parm_name, NULL));
2874 }
2875
2876 /**************************************************************************
2877  Determine the canonical name for a parameter.
2878  Indicate when it is an inverse (boolean) synonym instead of a
2879  "usual" synonym.
2880 **************************************************************************/
2881
2882 bool lp_canonicalize_parameter(const char *parm_name, const char **canon_parm,
2883                                bool *inverse)
2884 {
2885         int num;
2886
2887         if (!lp_parameter_is_valid(parm_name)) {
2888                 *canon_parm = NULL;
2889                 return False;
2890         }
2891
2892         num = map_parameter_canonical(parm_name, inverse);
2893         if (num < 0) {
2894                 /* parametric option */
2895                 *canon_parm = parm_name;
2896         } else {
2897                 *canon_parm = parm_table[num].label;
2898         }
2899
2900         return True;
2901
2902 }
2903
2904 /**************************************************************************
2905  Determine the canonical name for a parameter.
2906  Turn the value given into the inverse boolean expression when
2907  the synonym is an invers boolean synonym.
2908
2909  Return True if parm_name is a valid parameter name and
2910  in case it is an invers boolean synonym, if the val string could
2911  successfully be converted to the reverse bool.
2912  Return false in all other cases.
2913 **************************************************************************/
2914
2915 bool lp_canonicalize_parameter_with_value(const char *parm_name,
2916                                           const char *val,
2917                                           const char **canon_parm,
2918                                           const char **canon_val)
2919 {
2920         int num;
2921         bool inverse;
2922
2923         if (!lp_parameter_is_valid(parm_name)) {
2924                 *canon_parm = NULL;
2925                 *canon_val = NULL;
2926                 return False;
2927         }
2928
2929         num = map_parameter_canonical(parm_name, &inverse);
2930         if (num < 0) {
2931                 /* parametric option */
2932                 *canon_parm = parm_name;
2933                 *canon_val = val;
2934         } else {
2935                 *canon_parm = parm_table[num].label;
2936                 if (inverse) {
2937                         if (!lp_invert_boolean(val, canon_val)) {
2938                                 *canon_val = NULL;
2939                                 return False;
2940                         }
2941                 } else {
2942                         *canon_val = val;
2943                 }
2944         }
2945
2946         return True;
2947 }
2948
2949 /***************************************************************************
2950  Map a parameter's string representation to something we can use. 
2951  Returns False if the parameter string is not recognised, else TRUE.
2952 ***************************************************************************/
2953
2954 static int map_parameter(const char *pszParmName)
2955 {
2956         int iIndex;
2957
2958         if (*pszParmName == '-')
2959                 return (-1);
2960
2961         for (iIndex = 0; parm_table[iIndex].label; iIndex++)
2962                 if (strwicmp(parm_table[iIndex].label, pszParmName) == 0)
2963                         return (iIndex);
2964
2965         /* Warn only if it isn't parametric option */
2966         if (strchr(pszParmName, ':') == NULL)
2967                 DEBUG(0, ("Unknown parameter encountered: \"%s\"\n", pszParmName));
2968         /* We do return 'fail' for parametric options as well because they are
2969            stored in different storage
2970          */
2971         return (-1);
2972 }
2973
2974 /***************************************************************************
2975  Map a parameter's string representation to the index of the canonical
2976  form of the parameter (it might be a synonym).
2977  Returns -1 if the parameter string is not recognised.
2978 ***************************************************************************/
2979
2980 static int map_parameter_canonical(const char *pszParmName, bool *inverse)
2981 {
2982         int parm_num, canon_num;
2983         bool loc_inverse = False;
2984
2985         parm_num = map_parameter(pszParmName);
2986         if ((parm_num < 0) || !(parm_table[parm_num].flags & FLAG_HIDE)) {
2987                 /* invalid, parametric or no canidate for synonyms ... */
2988                 goto done;
2989         }
2990
2991         for (canon_num = 0; parm_table[canon_num].label; canon_num++) {
2992                 if (is_synonym_of(parm_num, canon_num, &loc_inverse)) {
2993                         parm_num = canon_num;
2994                         goto done;
2995                 }
2996         }
2997
2998 done:
2999         if (inverse != NULL) {
3000                 *inverse = loc_inverse;
3001         }
3002         return parm_num;
3003 }
3004
3005 /***************************************************************************
3006  return true if parameter number parm1 is a synonym of parameter
3007  number parm2 (parm2 being the principal name).
3008  set inverse to True if parm1 is P_BOOLREV and parm2 is P_BOOL,
3009  False otherwise.
3010 ***************************************************************************/
3011
3012 static bool is_synonym_of(int parm1, int parm2, bool *inverse)
3013 {
3014         if ((parm_table[parm1].ptr == parm_table[parm2].ptr) &&
3015             (parm_table[parm1].flags & FLAG_HIDE) &&
3016             !(parm_table[parm2].flags & FLAG_HIDE))
3017         {
3018                 if (inverse != NULL) {
3019                         if ((parm_table[parm1].type == P_BOOLREV) &&
3020                             (parm_table[parm2].type == P_BOOL))
3021                         {
3022                                 *inverse = True;
3023                         } else {
3024                                 *inverse = False;
3025                         }
3026                 }
3027                 return True;
3028         }
3029         return False;
3030 }
3031
3032 /***************************************************************************
3033  Show one parameter's name, type, [values,] and flags.
3034  (helper functions for show_parameter_list)
3035 ***************************************************************************/
3036
3037 static void show_parameter(int parmIndex)
3038 {
3039         int enumIndex, flagIndex;
3040         int parmIndex2;
3041         bool hadFlag;
3042         bool hadSyn;
3043         bool inverse;
3044         const char *type[] = { "P_BOOL", "P_BOOLREV", "P_CHAR", "P_INTEGER",
3045                 "P_OCTAL", "P_LIST", "P_STRING", "P_USTRING",
3046                 "P_ENUM", "P_SEP"};
3047         unsigned flags[] = { FLAG_BASIC, FLAG_SHARE, FLAG_PRINT, FLAG_GLOBAL,
3048                 FLAG_WIZARD, FLAG_ADVANCED, FLAG_DEVELOPER, FLAG_DEPRECATED,
3049                 FLAG_HIDE, FLAG_DOS_STRING};
3050         const char *flag_names[] = { "FLAG_BASIC", "FLAG_SHARE", "FLAG_PRINT",
3051                 "FLAG_GLOBAL", "FLAG_WIZARD", "FLAG_ADVANCED", "FLAG_DEVELOPER",
3052                 "FLAG_DEPRECATED", "FLAG_HIDE", "FLAG_DOS_STRING", NULL};
3053
3054         printf("%s=%s", parm_table[parmIndex].label,
3055                type[parm_table[parmIndex].type]);
3056         if (parm_table[parmIndex].type == P_ENUM) {
3057                 printf(",");
3058                 for (enumIndex=0;
3059                      parm_table[parmIndex].enum_list[enumIndex].name;
3060                      enumIndex++)
3061                 {
3062                         printf("%s%s",
3063                                enumIndex ? "|" : "",
3064                                parm_table[parmIndex].enum_list[enumIndex].name);
3065                 }
3066         }
3067         printf(",");
3068         hadFlag = False;
3069         for (flagIndex=0; flag_names[flagIndex]; flagIndex++) {
3070                 if (parm_table[parmIndex].flags & flags[flagIndex]) {
3071                         printf("%s%s",
3072                                 hadFlag ? "|" : "",
3073                                 flag_names[flagIndex]);
3074                         hadFlag = True;
3075                 }
3076         }
3077
3078         /* output synonyms */
3079         hadSyn = False;
3080         for (parmIndex2=0; parm_table[parmIndex2].label; parmIndex2++) {
3081                 if (is_synonym_of(parmIndex, parmIndex2, &inverse)) {
3082                         printf(" (%ssynonym of %s)", inverse ? "inverse " : "",
3083                                parm_table[parmIndex2].label);
3084                 } else if (is_synonym_of(parmIndex2, parmIndex, &inverse)) {
3085                         if (!hadSyn) {
3086                                 printf(" (synonyms: ");
3087                                 hadSyn = True;
3088                         } else {
3089                                 printf(", ");
3090                         }
3091                         printf("%s%s", parm_table[parmIndex2].label,
3092                                inverse ? "[i]" : "");
3093                 }
3094         }
3095         if (hadSyn) {
3096                 printf(")");
3097         }
3098
3099         printf("\n");
3100 }
3101
3102 /***************************************************************************
3103  Show all parameter's name, type, [values,] and flags.
3104 ***************************************************************************/
3105
3106 void show_parameter_list(void)
3107 {
3108         int classIndex, parmIndex;
3109         const char *section_names[] = { "local", "global", NULL};
3110
3111         for (classIndex=0; section_names[classIndex]; classIndex++) {
3112                 printf("[%s]\n", section_names[classIndex]);
3113                 for (parmIndex = 0; parm_table[parmIndex].label; parmIndex++) {
3114                         if (parm_table[parmIndex].p_class == classIndex) {
3115                                 show_parameter(parmIndex);
3116                         }
3117                 }
3118         }
3119 }
3120
3121 /***************************************************************************
3122  Set a boolean variable from the text value stored in the passed string.
3123  Returns True in success, False if the passed string does not correctly 
3124  represent a boolean.
3125 ***************************************************************************/
3126
3127 static bool set_boolean(bool *pb, const char *pszParmValue)
3128 {
3129         bool bRetval;
3130         bool value;
3131
3132         bRetval = True;
3133         value = False;
3134         if (strwicmp(pszParmValue, "yes") == 0 ||
3135             strwicmp(pszParmValue, "true") == 0 ||
3136             strwicmp(pszParmValue, "1") == 0)
3137                 value = True;
3138         else if (strwicmp(pszParmValue, "no") == 0 ||
3139                     strwicmp(pszParmValue, "False") == 0 ||
3140                     strwicmp(pszParmValue, "0") == 0)
3141                 value = False;
3142         else {
3143                 DEBUG(2,
3144                       ("ERROR: Badly formed boolean in configuration file: \"%s\".\n",
3145                        pszParmValue));
3146                 bRetval = False;
3147         }
3148
3149         if ((pb != NULL) && (bRetval != False)) {
3150                 *pb = value;
3151         }
3152
3153         return (bRetval);
3154 }
3155
3156
3157 /***************************************************************************
3158  Check if a given string correctly represents a boolean value.
3159 ***************************************************************************/
3160
3161 bool lp_string_is_valid_boolean(const char *parm_value)
3162 {
3163         return set_boolean(NULL, parm_value);
3164 }
3165
3166 /***************************************************************************
3167  Get the standard string representation of a boolean value ("yes" or "no")
3168 ***************************************************************************/
3169
3170 static const char *get_boolean(bool bool_value)
3171 {
3172         static const char *yes_str = "yes";
3173         static const char *no_str = "no";
3174
3175         return (bool_value ? yes_str : no_str);
3176 }
3177
3178 /***************************************************************************
3179  Provide the string of the negated boolean value associated to the boolean
3180  given as a string. Returns False if the passed string does not correctly
3181  represent a boolean.
3182 ***************************************************************************/
3183
3184 bool lp_invert_boolean(const char *str, const char **inverse_str)
3185 {
3186         bool val;
3187
3188         if (!set_boolean(&val, str)) {
3189                 return False;
3190         }
3191
3192         *inverse_str = get_boolean(!val);
3193         return True;
3194 }
3195
3196 /***************************************************************************
3197  Provide the canonical string representation of a boolean value given
3198  as a string. Return True on success, False if the string given does
3199  not correctly represent a boolean.
3200 ***************************************************************************/
3201
3202 bool lp_canonicalize_boolean(const char *str, const char**canon_str)
3203 {
3204         bool val;
3205
3206         if (!set_boolean(&val, str)) {
3207                 return False;
3208         }
3209
3210         *canon_str = get_boolean(val);
3211         return True;
3212 }
3213
3214 /***************************************************************************
3215 Find a service by name. Otherwise works like get_service.
3216 ***************************************************************************/
3217
3218 static int getservicebyname(const char *pszServiceName, service * pserviceDest)
3219 {
3220         int iService = -1;
3221         char *canon_name;
3222         TDB_DATA data;
3223
3224         if (ServiceHash == NULL) {
3225                 return -1;
3226         }
3227
3228         canon_name = canonicalize_servicename(pszServiceName);
3229
3230         data = dbwrap_fetch_bystring(ServiceHash, canon_name, canon_name);
3231
3232         if ((data.dptr != NULL) && (data.dsize == sizeof(iService))) {
3233                 iService = *(int *)data.dptr;
3234         }
3235
3236         TALLOC_FREE(canon_name);
3237
3238         if ((iService != -1) && (LP_SNUM_OK(iService))
3239             && (pserviceDest != NULL)) {
3240                 copy_service(pserviceDest, ServicePtrs[iService], NULL);
3241         }
3242
3243         return (iService);
3244 }
3245
3246 /***************************************************************************
3247  Copy a service structure to another.
3248  If pcopymapDest is NULL then copy all fields
3249 ***************************************************************************/
3250
3251 static void copy_service(service * pserviceDest, service * pserviceSource,
3252                          struct bitmap *pcopymapDest)
3253 {
3254         int i;
3255         bool bcopyall = (pcopymapDest == NULL);
3256         param_opt_struct *data, *pdata, *paramo;
3257         bool not_added;
3258
3259         for (i = 0; parm_table[i].label; i++)
3260                 if (parm_table[i].ptr && parm_table[i].p_class == P_LOCAL &&
3261                     (bcopyall || bitmap_query(pcopymapDest,i))) {
3262                         void *def_ptr = parm_table[i].ptr;
3263                         void *src_ptr =
3264                                 ((char *)pserviceSource) + PTR_DIFF(def_ptr,
3265                                                                     &sDefault);
3266                         void *dest_ptr =
3267                                 ((char *)pserviceDest) + PTR_DIFF(def_ptr,
3268                                                                   &sDefault);
3269
3270                         switch (parm_table[i].type) {
3271                                 case P_BOOL:
3272                                 case P_BOOLREV:
3273                                         *(bool *)dest_ptr = *(bool *)src_ptr;
3274                                         break;
3275
3276                                 case P_INTEGER:
3277                                 case P_ENUM:
3278                                 case P_OCTAL:
3279                                         *(int *)dest_ptr = *(int *)src_ptr;
3280                                         break;
3281
3282                                 case P_CHAR:
3283                                         *(char *)dest_ptr = *(char *)src_ptr;
3284                                         break;
3285
3286                                 case P_STRING:
3287                                         string_set((char **)dest_ptr,
3288                                                    *(char **)src_ptr);
3289                                         break;
3290
3291                                 case P_USTRING:
3292                                         string_set((char **)dest_ptr,
3293                                                    *(char **)src_ptr);
3294                                         strupper_m(*(char **)dest_ptr);
3295                                         break;
3296                                 case P_LIST:
3297                                         TALLOC_FREE(*((char ***)dest_ptr));
3298                                         str_list_copy(NULL, (char ***)dest_ptr,
3299                                                       *(const char ***)src_ptr);
3300                                         break;
3301                                 default:
3302                                         break;
3303                         }
3304                 }
3305
3306         if (bcopyall) {
3307                 init_copymap(pserviceDest);
3308                 if (pserviceSource->copymap)
3309                         bitmap_copy(pserviceDest->copymap,
3310                                     pserviceSource->copymap);
3311         }
3312         
3313         data = pserviceSource->param_opt;
3314         while (data) {
3315                 not_added = True;
3316                 pdata = pserviceDest->param_opt;
3317                 /* Traverse destination */
3318                 while (pdata) {
3319                         /* If we already have same option, override it */
3320                         if (strcmp(pdata->key, data->key) == 0) {
3321                                 string_free(&pdata->value);
3322                                 TALLOC_FREE(data->list);
3323                                 pdata->value = SMB_STRDUP(data->value);
3324                                 not_added = False;
3325                                 break;
3326                         }
3327                         pdata = pdata->next;
3328                 }
3329                 if (not_added) {
3330                     paramo = SMB_XMALLOC_P(param_opt_struct);
3331                     paramo->key = SMB_STRDUP(data->key);
3332                     paramo->value = SMB_STRDUP(data->value);
3333                     paramo->list = NULL;
3334                     DLIST_ADD(pserviceDest->param_opt, paramo);
3335                 }
3336                 data = data->next;
3337         }
3338 }
3339
3340 /***************************************************************************
3341 Check a service for consistency. Return False if the service is in any way
3342 incomplete or faulty, else True.
3343 ***************************************************************************/
3344
3345 bool service_ok(int iService)
3346 {
3347         bool bRetval;
3348
3349         bRetval = True;
3350         if (ServicePtrs[iService]->szService[0] == '\0') {
3351                 DEBUG(0, ("The following message indicates an internal error:\n"));
3352                 DEBUG(0, ("No service name in service entry.\n"));
3353                 bRetval = False;
3354         }
3355
3356         /* The [printers] entry MUST be printable. I'm all for flexibility, but */
3357         /* I can't see why you'd want a non-printable printer service...        */
3358         if (strwicmp(ServicePtrs[iService]->szService, PRINTERS_NAME) == 0) {
3359                 if (!ServicePtrs[iService]->bPrint_ok) {
3360                         DEBUG(0, ("WARNING: [%s] service MUST be printable!\n",
3361                                ServicePtrs[iService]->szService));
3362                         ServicePtrs[iService]->bPrint_ok = True;
3363                 }
3364                 /* [printers] service must also be non-browsable. */
3365                 if (ServicePtrs[iService]->bBrowseable)
3366                         ServicePtrs[iService]->bBrowseable = False;
3367         }
3368
3369         if (ServicePtrs[iService]->szPath[0] == '\0' &&
3370             strwicmp(ServicePtrs[iService]->szService, HOMES_NAME) != 0 &&
3371             ServicePtrs[iService]->szMSDfsProxy[0] == '\0'
3372             ) {
3373                 DEBUG(0, ("WARNING: No path in service %s - making it unavailable!\n",
3374                         ServicePtrs[iService]->szService));
3375                 ServicePtrs[iService]->bAvailable = False;
3376         }
3377
3378         /* If a service is flagged unavailable, log the fact at level 1. */
3379         if (!ServicePtrs[iService]->bAvailable)
3380                 DEBUG(1, ("NOTE: Service %s is flagged unavailable.\n",
3381                           ServicePtrs[iService]->szService));
3382
3383         return (bRetval);
3384 }
3385
3386 /*
3387  * process_registry_globals
3388  */
3389 static bool process_registry_globals(bool (*pfunc)(const char *, const char *))
3390 {
3391         WERROR werr;
3392         char **param_names;
3393         char **param_values;
3394         uint32_t num_params;
3395         uint32_t count;
3396         TALLOC_CTX *mem_ctx = talloc_stackframe();
3397         bool ret = false;
3398
3399         if (conf_ctx == NULL) {
3400                 /* first time */
3401                 werr = libnet_conf_open(NULL, &conf_ctx);
3402                 if (!W_ERROR_IS_OK(werr)) {
3403                         goto done;
3404                 }
3405         }
3406
3407         werr = libnet_conf_get_share(mem_ctx, conf_ctx, GLOBAL_NAME,
3408                                      &num_params, &param_names, &param_values);
3409         if (!W_ERROR_IS_OK(werr)) {
3410                 goto done;
3411         }
3412
3413         for (count = 0; count < num_params; count++) {
3414                 ret = pfunc(param_names[count], param_values[count]);
3415                 if (ret != true) {
3416                         goto done;
3417                 }
3418         }
3419
3420         ret = pfunc("registry shares", "yes");
3421         conf_last_seqnum = libnet_conf_get_seqnum(conf_ctx, NULL, NULL);
3422
3423 done:
3424         TALLOC_FREE(mem_ctx);
3425         return ret;
3426 }
3427
3428 static struct file_lists {
3429         struct file_lists *next;
3430         char *name;
3431         char *subfname;
3432         time_t modtime;
3433 } *file_lists = NULL;
3434
3435 /*******************************************************************
3436  Keep a linked list of all config files so we know when one has changed 
3437  it's date and needs to be reloaded.
3438 ********************************************************************/
3439
3440 static void add_to_file_list(const char *fname, const char *subfname)
3441 {
3442         struct file_lists *f = file_lists;
3443
3444         while (f) {
3445                 if (f->name && !strcmp(f->name, fname))
3446                         break;
3447                 f = f->next;
3448         }
3449
3450         if (!f) {
3451                 f = SMB_MALLOC_P(struct file_lists);
3452                 if (!f)
3453                         return;
3454                 f->next = file_lists;
3455                 f->name = SMB_STRDUP(fname);
3456                 if (!f->name) {
3457                         SAFE_FREE(f);
3458                         return;
3459                 }
3460                 f->subfname = SMB_STRDUP(subfname);
3461                 if (!f->subfname) {
3462                         SAFE_FREE(f);
3463                         return;
3464                 }
3465                 file_lists = f;
3466                 f->modtime = file_modtime(subfname);
3467         } else {
3468                 time_t t = file_modtime(subfname);
3469                 if (t)
3470                         f->modtime = t;
3471         }
3472 }
3473
3474 /**
3475  * Utility function for outsiders to check if we're running on registry.
3476  */
3477 bool lp_config_backend_is_registry(void)
3478 {
3479         return (lp_config_backend() == CONFIG_BACKEND_REGISTRY);
3480 }
3481
3482 /*******************************************************************
3483  Check if a config file has changed date.
3484 ********************************************************************/
3485
3486 bool lp_file_list_changed(void)
3487 {
3488         struct file_lists *f = file_lists;
3489
3490         DEBUG(6, ("lp_file_list_changed()\n"));
3491
3492         if (lp_config_backend() == CONFIG_BACKEND_REGISTRY) {
3493                 uint64_t conf_cur_seqnum;
3494                 if (conf_ctx == NULL) {
3495                         WERROR werr;
3496                         werr = libnet_conf_open(NULL, &conf_ctx);
3497                         if (!W_ERROR_IS_OK(werr)) {
3498                                 DEBUG(0, ("error opening configuration: %s\n",
3499                                           dos_errstr(werr)));
3500                                 return false;
3501                         }
3502                 }
3503                 conf_cur_seqnum = libnet_conf_get_seqnum(conf_ctx, NULL, NULL);
3504                 if (conf_last_seqnum != conf_cur_seqnum) {
3505                         DEBUGADD(6, ("regdb seqnum changed: old = %llu, "
3506                                      "new = %llu\n",
3507                                      (unsigned long long)conf_last_seqnum,
3508                                      (unsigned long long)conf_cur_seqnum));
3509                         return true;
3510                 } else {
3511                         /*
3512                          * Don't check files when config_backend is registry.
3513                          * Remove this to obtain checking of files even with
3514                          * registry config backend. That would enable switching
3515                          * off registry configuration by changing smb.conf even
3516                          * without restarting smbd.
3517                          */
3518                         return false;
3519                 }
3520         }
3521
3522         while (f) {
3523                 char *n2 = NULL;
3524                 time_t mod_time;
3525
3526                 n2 = alloc_sub_basic(get_current_username(),
3527                                     current_user_info.domain,
3528                                     f->name);
3529                 if (!n2) {
3530                         return false;
3531                 }
3532                 DEBUGADD(6, ("file %s -> %s  last mod_time: %s\n",
3533                              f->name, n2, ctime(&f->modtime)));
3534
3535                 mod_time = file_modtime(n2);
3536
3537                 if (mod_time && ((f->modtime != mod_time) || (f->subfname == NULL) || (strcmp(n2, f->subfname) != 0))) {
3538                         DEBUGADD(6,
3539                                  ("file %s modified: %s\n", n2,
3540                                   ctime(&mod_time)));
3541                         f->modtime = mod_time;
3542                         SAFE_FREE(f->subfname);
3543                         f->subfname = n2; /* Passing ownership of
3544                                              return from alloc_sub_basic
3545                                              above. */
3546                         return true;
3547                 }
3548                 SAFE_FREE(n2);
3549                 f = f->next;
3550         }
3551         return (False);
3552 }
3553
3554
3555 /***************************************************************************
3556  Run standard_sub_basic on netbios name... needed because global_myname
3557  is not accessed through any lp_ macro.
3558  Note: We must *NOT* use string_set() here as ptr points to global_myname.
3559 ***************************************************************************/
3560
3561 static bool handle_netbios_name(int snum, const char *pszParmValue, char **ptr)
3562 {
3563         bool ret;
3564         char *netbios_name = alloc_sub_basic(get_current_username(),
3565                                         current_user_info.domain,
3566                                         pszParmValue);
3567
3568         ret = set_global_myname(netbios_name);
3569         SAFE_FREE(netbios_name);
3570         string_set(&Globals.szNetbiosName,global_myname());
3571
3572         DEBUG(4, ("handle_netbios_name: set global_myname to: %s\n",
3573                global_myname()));
3574
3575         return ret;
3576 }
3577
3578 static bool handle_charset(int snum, const char *pszParmValue, char **ptr)
3579 {
3580         if (strcmp(*ptr, pszParmValue) != 0) {
3581                 string_set(ptr, pszParmValue);
3582                 init_iconv();
3583         }
3584         return True;
3585 }
3586
3587
3588
3589 static bool handle_workgroup(int snum, const char *pszParmValue, char **ptr)
3590 {
3591         bool ret;
3592         
3593         ret = set_global_myworkgroup(pszParmValue);
3594         string_set(&Globals.szWorkgroup,lp_workgroup());
3595         
3596         return ret;
3597 }
3598
3599 static bool handle_netbios_scope(int snum, const char *pszParmValue, char **ptr)
3600 {
3601         bool ret;
3602         
3603         ret = set_global_scope(pszParmValue);
3604         string_set(&Globals.szNetbiosScope,global_scope());
3605
3606         return ret;
3607 }
3608
3609 static bool handle_netbios_aliases(int snum, const char *pszParmValue, char **ptr)
3610 {
3611         TALLOC_FREE(Globals.szNetbiosAliases);
3612         Globals.szNetbiosAliases = str_list_make(NULL, pszParmValue, NULL);
3613         return set_netbios_aliases((const char **)Globals.szNetbiosAliases);
3614 }
3615
3616 /***************************************************************************
3617  Handle the include operation.
3618 ***************************************************************************/
3619
3620 static bool handle_include(int snum, const char *pszParmValue, char **ptr)
3621 {
3622         char *fname;
3623
3624         fname = alloc_sub_basic(get_current_username(),
3625                                 current_user_info.domain,
3626                                 pszParmValue);
3627
3628         add_to_file_list(pszParmValue, fname);
3629
3630         string_set(ptr, fname);
3631
3632         if (file_exist(fname, NULL)) {
3633                 bool ret = pm_process(fname, do_section, do_parameter);
3634                 SAFE_FREE(fname);
3635                 return ret;
3636         }
3637
3638         DEBUG(2, ("Can't find include file %s\n", fname));
3639         SAFE_FREE(fname);
3640         return false;
3641 }
3642
3643 /***************************************************************************
3644  Handle the interpretation of the copy parameter.
3645 ***************************************************************************/
3646
3647 static bool handle_copy(int snum, const char *pszParmValue, char **ptr)
3648 {
3649         bool bRetval;
3650         int iTemp;
3651         service serviceTemp;
3652
3653         string_set(ptr, pszParmValue);
3654
3655         init_service(&serviceTemp);
3656
3657         bRetval = False;
3658
3659         DEBUG(3, ("Copying service from service %s\n", pszParmValue));
3660
3661         if ((iTemp = getservicebyname(pszParmValue, &serviceTemp)) >= 0) {
3662                 if (iTemp == iServiceIndex) {
3663                         DEBUG(0, ("Can't copy service %s - unable to copy self!\n", pszParmValue));
3664                 } else {
3665                         copy_service(ServicePtrs[iServiceIndex],
3666                                      &serviceTemp,
3667                                      ServicePtrs[iServiceIndex]->copymap);
3668                         bRetval = True;
3669                 }
3670         } else {
3671                 DEBUG(0, ("Unable to copy service - source not found: %s\n", pszParmValue));
3672                 bRetval = False;
3673         }
3674
3675         free_service(&serviceTemp);
3676         return (bRetval);
3677 }
3678
3679 static bool handle_ldap_debug_level(int snum, const char *pszParmValue, char **ptr)
3680 {
3681         Globals.ldap_debug_level = lp_int(pszParmValue);
3682         init_ldap_debugging();
3683         return true;
3684 }
3685
3686 /***************************************************************************
3687  Handle idmap/non unix account uid and gid allocation parameters.  The format of these
3688  parameters is:
3689
3690  [global]
3691
3692         idmap uid = 1000-1999
3693         idmap gid = 700-899
3694
3695  We only do simple parsing checks here.  The strings are parsed into useful
3696  structures in the idmap daemon code.
3697
3698 ***************************************************************************/
3699
3700 /* Some lp_ routines to return idmap [ug]id information */
3701
3702 static uid_t idmap_uid_low, idmap_uid_high;
3703 static gid_t idmap_gid_low, idmap_gid_high;
3704
3705 bool lp_idmap_uid(uid_t *low, uid_t *high)
3706 {
3707         if (idmap_uid_low == 0 || idmap_uid_high == 0)
3708                 return False;
3709
3710         if (low)
3711                 *low = idmap_uid_low;
3712
3713         if (high)
3714                 *high = idmap_uid_high;
3715
3716         return True;
3717 }
3718
3719 bool lp_idmap_gid(gid_t *low, gid_t *high)
3720 {
3721         if (idmap_gid_low == 0 || idmap_gid_high == 0)
3722                 return False;
3723
3724         if (low)
3725                 *low = idmap_gid_low;
3726
3727         if (high)
3728                 *high = idmap_gid_high;
3729
3730         return True;
3731 }
3732
3733 /* Do some simple checks on "idmap [ug]id" parameter values */
3734
3735 static bool handle_idmap_uid(int snum, const char *pszParmValue, char **ptr)
3736 {
3737         uint32 low, high;
3738
3739         if (sscanf(pszParmValue, "%u - %u", &low, &high) != 2 || high < low)
3740                 return False;
3741
3742         /* Parse OK */
3743
3744         string_set(ptr, pszParmValue);
3745
3746         idmap_uid_low = low;
3747         idmap_uid_high = high;
3748
3749         return True;
3750 }
3751
3752 static bool handle_idmap_gid(int snum, const char *pszParmValue, char **ptr)
3753 {
3754         uint32 low, high;
3755
3756         if (sscanf(pszParmValue, "%u - %u", &low, &high) != 2 || high < low)
3757                 return False;
3758
3759         /* Parse OK */
3760
3761         string_set(ptr, pszParmValue);
3762
3763         idmap_gid_low = low;
3764         idmap_gid_high = high;
3765
3766         return True;
3767 }
3768
3769 /***************************************************************************
3770  Handle the DEBUG level list.
3771 ***************************************************************************/
3772
3773 static bool handle_debug_list( int snum, const char *pszParmValueIn, char **ptr )
3774 {
3775         string_set(ptr, pszParmValueIn);
3776         return debug_parse_levels(pszParmValueIn);
3777 }
3778
3779 /***************************************************************************
3780  Handle ldap suffixes - default to ldapsuffix if sub-suffixes are not defined.
3781 ***************************************************************************/
3782
3783 static const char *append_ldap_suffix( const char *str )
3784 {
3785         const char *suffix_string;
3786
3787
3788         suffix_string = talloc_asprintf(talloc_tos(), "%s,%s", str,
3789                                         Globals.szLdapSuffix );
3790         if ( !suffix_string ) {
3791                 DEBUG(0,("append_ldap_suffix: talloc_asprintf() failed!\n"));
3792                 return "";
3793         }
3794
3795         return suffix_string;
3796 }
3797
3798 const char *lp_ldap_machine_suffix(void)
3799 {
3800         if (Globals.szLdapMachineSuffix[0])
3801                 return append_ldap_suffix(Globals.szLdapMachineSuffix);
3802
3803         return lp_string(Globals.szLdapSuffix);
3804 }
3805
3806 const char *lp_ldap_user_suffix(void)
3807 {
3808         if (Globals.szLdapUserSuffix[0])
3809                 return append_ldap_suffix(Globals.szLdapUserSuffix);
3810
3811         return lp_string(Globals.szLdapSuffix);
3812 }
3813
3814 const char *lp_ldap_group_suffix(void)
3815 {
3816         if (Globals.szLdapGroupSuffix[0])
3817                 return append_ldap_suffix(Globals.szLdapGroupSuffix);
3818
3819         return lp_string(Globals.szLdapSuffix);
3820 }
3821
3822 const char *lp_ldap_idmap_suffix(void)
3823 {
3824         if (Globals.szLdapIdmapSuffix[0])
3825                 return append_ldap_suffix(Globals.szLdapIdmapSuffix);
3826
3827         return lp_string(Globals.szLdapSuffix);
3828 }
3829
3830 /****************************************************************************
3831  set the value for a P_ENUM
3832  ***************************************************************************/
3833
3834 static void lp_set_enum_parm( struct parm_struct *parm, const char *pszParmValue,
3835                               int *ptr )
3836 {
3837         int i;
3838
3839         for (i = 0; parm->enum_list[i].name; i++) {
3840                 if ( strequal(pszParmValue, parm->enum_list[i].name)) {
3841                         *ptr = parm->enum_list[i].value;
3842                         break;
3843                 }
3844         }
3845 }
3846
3847 /***************************************************************************
3848 ***************************************************************************/
3849
3850 static bool handle_printing(int snum, const char *pszParmValue, char **ptr)
3851 {
3852         static int parm_num = -1;
3853         service *s;
3854
3855         if ( parm_num == -1 )
3856                 parm_num = map_parameter( "printing" );
3857
3858         lp_set_enum_parm( &parm_table[parm_num], pszParmValue, (int*)ptr );
3859
3860         if ( snum < 0 )
3861                 s = &sDefault;
3862         else
3863                 s = ServicePtrs[snum];
3864
3865         init_printer_values( s );
3866
3867         return True;
3868 }
3869
3870
3871 /***************************************************************************
3872  Initialise a copymap.
3873 ***************************************************************************/
3874
3875 static void init_copymap(service * pservice)
3876 {
3877         int i;
3878         if (pservice->copymap) {
3879                 bitmap_free(pservice->copymap);
3880         }
3881         pservice->copymap = bitmap_allocate(NUMPARAMETERS);
3882         if (!pservice->copymap)
3883                 DEBUG(0,
3884                       ("Couldn't allocate copymap!! (size %d)\n",
3885                        (int)NUMPARAMETERS));
3886         else
3887                 for (i = 0; i < NUMPARAMETERS; i++)
3888                         bitmap_set(pservice->copymap, i);
3889 }
3890
3891 /***************************************************************************
3892  Return the local pointer to a parameter given the service number and the 
3893  pointer into the default structure.
3894 ***************************************************************************/
3895
3896 void *lp_local_ptr(int snum, void *ptr)
3897 {
3898         return (void *)(((char *)ServicePtrs[snum]) + PTR_DIFF(ptr, &sDefault));
3899 }
3900
3901 /***************************************************************************
3902  Process a parameter for a particular service number. If snum < 0
3903  then assume we are in the globals.
3904 ***************************************************************************/
3905
3906 bool lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue)
3907 {
3908         int parmnum, i, slen;
3909         void *parm_ptr = NULL;  /* where we are going to store the result */
3910         void *def_ptr = NULL;
3911         char *param_key = NULL;
3912         char *sep;
3913         param_opt_struct *paramo, *data;
3914         bool not_added;
3915
3916         parmnum = map_parameter(pszParmName);
3917
3918         if (parmnum < 0) {
3919                 if ((sep=strchr(pszParmName, ':')) != NULL) {
3920                         TALLOC_CTX *frame = talloc_stackframe();
3921
3922                         *sep = '\0';
3923                         param_key = talloc_asprintf(frame, "%s:", pszParmName);
3924                         if (!param_key) {
3925                                 TALLOC_FREE(frame);
3926                                 return false;
3927                         }
3928                         slen = strlen(param_key);
3929                         param_key = talloc_asprintf_append(param_key, sep+1);
3930                         if (!param_key) {
3931                                 TALLOC_FREE(frame);
3932                                 return false;
3933                         }
3934                         trim_char(param_key+slen, ' ', ' ');
3935                         not_added = True;
3936                         data = (snum < 0) ? Globals.param_opt :
3937                                 ServicePtrs[snum]->param_opt;
3938                         /* Traverse destination */
3939                         while (data) {
3940                                 /* If we already have same option, override it */
3941                                 if (strcmp(data->key, param_key) == 0) {
3942                                         string_free(&data->value);
3943                                         TALLOC_FREE(data->list);
3944                                         data->value = SMB_STRDUP(pszParmValue);
3945                                         not_added = False;
3946                                         break;
3947                                 }
3948                                 data = data->next;
3949                         }
3950                         if (not_added) {
3951                                 paramo = SMB_XMALLOC_P(param_opt_struct);
3952                                 paramo->key = SMB_STRDUP(param_key);
3953                                 paramo->value = SMB_STRDUP(pszParmValue);
3954                                 paramo->list = NULL;
3955                                 if (snum < 0) {
3956                                         DLIST_ADD(Globals.param_opt, paramo);
3957                                 } else {
3958                                         DLIST_ADD(ServicePtrs[snum]->param_opt, paramo);
3959                                 }
3960                         }
3961
3962                         *sep = ':';
3963                         TALLOC_FREE(frame);
3964                         return (True);
3965                 }
3966                 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n", pszParmName));
3967                 return (True);
3968         }
3969
3970         if (parm_table[parmnum].flags & FLAG_DEPRECATED) {
3971                 DEBUG(1, ("WARNING: The \"%s\" option is deprecated\n",
3972                           pszParmName));
3973         }
3974
3975         def_ptr = parm_table[parmnum].ptr;
3976
3977         /* we might point at a service, the default service or a global */
3978         if (snum < 0) {
3979                 parm_ptr = def_ptr;
3980         } else {
3981                 if (parm_table[parmnum].p_class == P_GLOBAL) {
3982                         DEBUG(0,
3983                               ("Global parameter %s found in service section!\n",
3984                                pszParmName));
3985                         return (True);
3986                 }
3987                 parm_ptr =
3988                         ((char *)ServicePtrs[snum]) + PTR_DIFF(def_ptr,
3989                                                             &sDefault);
3990         }
3991
3992         if (snum >= 0) {
3993                 if (!ServicePtrs[snum]->copymap)
3994                         init_copymap(ServicePtrs[snum]);
3995
3996                 /* this handles the aliases - set the copymap for other entries with
3997                    the same data pointer */
3998                 for (i = 0; parm_table[i].label; i++)
3999                         if (parm_table[i].ptr == parm_table[parmnum].ptr)
4000                                 bitmap_clear(ServicePtrs[snum]->copymap, i);
4001         }
4002
4003         /* if it is a special case then go ahead */
4004         if (parm_table[parmnum].special) {
4005                 parm_table[parmnum].special(snum, pszParmValue, (char **)parm_ptr);
4006                 return (True);
4007         }
4008
4009         /* now switch on the type of variable it is */
4010         switch (parm_table[parmnum].type)
4011         {
4012                 case P_BOOL:
4013                         *(bool *)parm_ptr = lp_bool(pszParmValue);
4014                         break;
4015
4016                 case P_BOOLREV:
4017                         *(bool *)parm_ptr = !lp_bool(pszParmValue);
4018                         break;
4019
4020                 case P_INTEGER:
4021                         *(int *)parm_ptr = lp_int(pszParmValue);
4022                         break;
4023
4024                 case P_CHAR:
4025                         *(char *)parm_ptr = *pszParmValue;
4026                         break;
4027
4028                 case P_OCTAL:
4029                         i = sscanf(pszParmValue, "%o", (int *)parm_ptr);
4030                         if ( i != 1 ) {
4031                             DEBUG ( 0, ("Invalid octal number %s\n", pszParmName ));
4032                         }
4033                         break;
4034
4035                 case P_LIST:
4036                         TALLOC_FREE(*((char ***)parm_ptr));
4037                         *(char ***)parm_ptr = str_list_make(
4038                                 NULL, pszParmValue, NULL);
4039                         break;
4040
4041                 case P_STRING:
4042                         string_set((char **)parm_ptr, pszParmValue);
4043                         break;
4044
4045                 case P_USTRING:
4046                         string_set((char **)parm_ptr, pszParmValue);
4047                         strupper_m(*(char **)parm_ptr);
4048                         break;
4049
4050                 case P_ENUM:
4051                         lp_set_enum_parm( &parm_table[parmnum], pszParmValue, (int*)parm_ptr );
4052                         break;
4053                 case P_SEP:
4054                         break;
4055         }
4056
4057         return (True);
4058 }
4059
4060 /***************************************************************************
4061  Process a parameter.
4062 ***************************************************************************/
4063
4064 static bool do_parameter(const char *pszParmName, const char *pszParmValue)
4065 {
4066         if (!bInGlobalSection && bGlobalOnly)
4067                 return (True);
4068
4069         DEBUGADD(4, ("doing parameter %s = %s\n", pszParmName, pszParmValue));
4070
4071         return (lp_do_parameter(bInGlobalSection ? -2 : iServiceIndex,
4072                                 pszParmName, pszParmValue));
4073 }
4074
4075 /***************************************************************************
4076  Print a parameter of the specified type.
4077 ***************************************************************************/
4078
4079 static void print_parameter(struct parm_struct *p, void *ptr, FILE * f)
4080 {
4081         int i;
4082         switch (p->type)
4083         {
4084                 case P_ENUM:
4085                         for (i = 0; p->enum_list[i].name; i++) {
4086                                 if (*(int *)ptr == p->enum_list[i].value) {
4087                                         fprintf(f, "%s",
4088                                                 p->enum_list[i].name);
4089                                         break;
4090                                 }
4091                         }
4092                         break;
4093
4094                 case P_BOOL:
4095                         fprintf(f, "%s", BOOLSTR(*(bool *)ptr));
4096                         break;
4097
4098                 case P_BOOLREV:
4099                         fprintf(f, "%s", BOOLSTR(!*(bool *)ptr));
4100                         break;
4101
4102                 case P_INTEGER:
4103                         fprintf(f, "%d", *(int *)ptr);
4104                         break;
4105
4106                 case P_CHAR:
4107                         fprintf(f, "%c", *(char *)ptr);
4108                         break;
4109
4110                 case P_OCTAL: {
4111                         char *o = octal_string(*(int *)ptr);
4112                         fprintf(f, "%s", o);
4113                         TALLOC_FREE(o);
4114                         break;
4115                 }
4116
4117                 case P_LIST:
4118                         if ((char ***)ptr && *(char ***)ptr) {
4119                                 char **list = *(char ***)ptr;
4120                                 for (; *list; list++) {
4121                                         /* surround strings with whitespace in double quotes */
4122                                         if ( strchr_m( *list, ' ' ) )
4123                                                 fprintf(f, "\"%s\"%s", *list, ((*(list+1))?", ":""));
4124                                         else
4125                                                 fprintf(f, "%s%s", *list, ((*(list+1))?", ":""));
4126                                 }
4127                         }
4128                         break;
4129
4130                 case P_STRING:
4131                 case P_USTRING:
4132                         if (*(char **)ptr) {
4133                                 fprintf(f, "%s", *(char **)ptr);
4134                         }
4135                         break;
4136                 case P_SEP:
4137                         break;
4138         }
4139 }
4140
4141 /***************************************************************************
4142  Check if two parameters are equal.
4143 ***************************************************************************/
4144
4145 static bool equal_parameter(parm_type type, void *ptr1, void *ptr2)
4146 {
4147         switch (type) {
4148                 case P_BOOL:
4149                 case P_BOOLREV:
4150                         return (*((bool *)ptr1) == *((bool *)ptr2));
4151
4152                 case P_INTEGER:
4153                 case P_ENUM:
4154                 case P_OCTAL:
4155                         return (*((int *)ptr1) == *((int *)ptr2));
4156
4157                 case P_CHAR:
4158                         return (*((char *)ptr1) == *((char *)ptr2));
4159
4160                 case P_LIST:
4161                         return str_list_compare(*(char ***)ptr1, *(char ***)ptr2);
4162
4163                 case P_STRING:
4164                 case P_USTRING:
4165                 {
4166                         char *p1 = *(char **)ptr1, *p2 = *(char **)ptr2;
4167                         if (p1 && !*p1)
4168                                 p1 = NULL;
4169                         if (p2 && !*p2)
4170                                 p2 = NULL;
4171                         return (p1 == p2 || strequal(p1, p2));
4172                 }
4173                 case P_SEP:
4174                         break;
4175         }
4176         return (False);
4177 }
4178
4179 /***************************************************************************
4180  Initialize any local varients in the sDefault table.
4181 ***************************************************************************/
4182
4183 void init_locals(void)
4184 {
4185         /* None as yet. */
4186 }
4187
4188 /***************************************************************************
4189  Process a new section (service). At this stage all sections are services.
4190  Later we'll have special sections that permit server parameters to be set.
4191  Returns True on success, False on failure. 
4192 ***************************************************************************/
4193
4194 static bool do_section(const char *pszSectionName)
4195 {
4196         bool bRetval;
4197         bool isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
4198                          (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
4199         bRetval = False;
4200
4201         /* if we were in a global section then do the local inits */
4202         if (bInGlobalSection && !isglobal)
4203                 init_locals();
4204
4205         /* if we've just struck a global section, note the fact. */
4206         bInGlobalSection = isglobal;
4207
4208         /* check for multiple global sections */
4209         if (bInGlobalSection) {
4210                 DEBUG(3, ("Processing section \"[%s]\"\n", pszSectionName));
4211                 return (True);
4212         }
4213
4214         if (!bInGlobalSection && bGlobalOnly)
4215                 return (True);
4216
4217         /* if we have a current service, tidy it up before moving on */
4218         bRetval = True;
4219
4220         if (iServiceIndex >= 0)
4221                 bRetval = service_ok(iServiceIndex);
4222
4223         /* if all is still well, move to the next record in the services array */
4224         if (bRetval) {
4225                 /* We put this here to avoid an odd message order if messages are */
4226                 /* issued by the post-processing of a previous section. */
4227                 DEBUG(2, ("Processing section \"[%s]\"\n", pszSectionName));
4228
4229                 if ((iServiceIndex = add_a_service(&sDefault, pszSectionName))
4230                     < 0) {
4231                         DEBUG(0, ("Failed to add a new service\n"));
4232                         return (False);
4233                 }
4234         }
4235
4236         return (bRetval);
4237 }
4238
4239
4240 /***************************************************************************
4241  Determine if a partcular base parameter is currentl set to the default value.
4242 ***************************************************************************/
4243
4244 static bool is_default(int i)
4245 {
4246         if (!defaults_saved)
4247                 return False;
4248         switch (parm_table[i].type) {
4249                 case P_LIST:
4250                         return str_list_compare (parm_table[i].def.lvalue, 
4251                                                 *(char ***)parm_table[i].ptr);
4252                 case P_STRING:
4253                 case P_USTRING:
4254                         return strequal(parm_table[i].def.svalue,
4255                                         *(char **)parm_table[i].ptr);
4256                 case P_BOOL:
4257                 case P_BOOLREV:
4258                         return parm_table[i].def.bvalue ==
4259                                 *(bool *)parm_table[i].ptr;
4260                 case P_CHAR:
4261                         return parm_table[i].def.cvalue ==
4262                                 *(char *)parm_table[i].ptr;
4263                 case P_INTEGER:
4264                 case P_OCTAL:
4265                 case P_ENUM:
4266                         return parm_table[i].def.ivalue ==
4267                                 *(int *)parm_table[i].ptr;
4268                 case P_SEP:
4269                         break;
4270         }
4271         return False;
4272 }
4273
4274 /***************************************************************************
4275 Display the contents of the global structure.
4276 ***************************************************************************/
4277
4278 static void dump_globals(FILE *f)
4279 {
4280         int i;
4281         param_opt_struct *data;
4282         
4283         fprintf(f, "[global]\n");
4284
4285         for (i = 0; parm_table[i].label; i++)
4286                 if (parm_table[i].p_class == P_GLOBAL &&
4287                     parm_table[i].ptr &&
4288                     (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) {
4289                         if (defaults_saved && is_default(i))
4290                                 continue;
4291                         fprintf(f, "\t%s = ", parm_table[i].label);
4292                         print_parameter(&parm_table[i], parm_table[i].ptr, f);
4293                         fprintf(f, "\n");
4294         }
4295         if (Globals.param_opt != NULL) {
4296                 data = Globals.param_opt;
4297                 while(data) {
4298                         fprintf(f, "\t%s = %s\n", data->key, data->value);
4299                         data = data->next;
4300                 }
4301         }
4302
4303 }
4304
4305 /***************************************************************************
4306  Return True if a local parameter is currently set to the global default.
4307 ***************************************************************************/
4308
4309 bool lp_is_default(int snum, struct parm_struct *parm)
4310 {
4311         int pdiff = PTR_DIFF(parm->ptr, &sDefault);
4312
4313         return equal_parameter(parm->type,
4314                                ((char *)ServicePtrs[snum]) + pdiff,
4315                                ((char *)&sDefault) + pdiff);
4316 }
4317
4318 /***************************************************************************
4319  Display the contents of a single services record.
4320 ***************************************************************************/
4321
4322 static void dump_a_service(service * pService, FILE * f)
4323 {
4324         int i;
4325         param_opt_struct *data;
4326         
4327         if (pService != &sDefault)
4328                 fprintf(f, "[%s]\n", pService->szService);
4329
4330         for (i = 0; parm_table[i].label; i++) {
4331
4332                 if (parm_table[i].p_class == P_LOCAL &&
4333                     parm_table[i].ptr &&
4334                     (*parm_table[i].label != '-') &&
4335                     (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) 
4336                 {
4337                 
4338                         int pdiff = PTR_DIFF(parm_table[i].ptr, &sDefault);
4339
4340                         if (pService == &sDefault) {
4341                                 if (defaults_saved && is_default(i))
4342                                         continue;
4343                         } else {
4344                                 if (equal_parameter(parm_table[i].type,
4345                                                     ((char *)pService) +
4346                                                     pdiff,
4347                                                     ((char *)&sDefault) +
4348                                                     pdiff))
4349                                         continue;
4350                         }
4351
4352                         fprintf(f, "\t%s = ", parm_table[i].label);
4353                         print_parameter(&parm_table[i],
4354                                         ((char *)pService) + pdiff, f);
4355                         fprintf(f, "\n");
4356                 }
4357         }
4358
4359                 if (pService->param_opt != NULL) {
4360                         data = pService->param_opt;
4361                         while(data) {
4362                                 fprintf(f, "\t%s = %s\n", data->key, data->value);
4363                                 data = data->next;
4364                         }
4365                 }
4366 }
4367
4368 /***************************************************************************
4369  Display the contents of a parameter of a single services record.
4370 ***************************************************************************/
4371
4372 bool dump_a_parameter(int snum, char *parm_name, FILE * f, bool isGlobal)
4373 {
4374         int i;
4375         bool result = False;
4376         parm_class p_class;
4377         unsigned flag = 0;
4378         fstring local_parm_name;
4379         char *parm_opt;
4380         const char *parm_opt_value;
4381
4382         /* check for parametrical option */
4383         fstrcpy( local_parm_name, parm_name);
4384         parm_opt = strchr( local_parm_name, ':');
4385
4386         if (parm_opt) {
4387                 *parm_opt = '\0';
4388                 parm_opt++;
4389                 if (strlen(parm_opt)) {
4390                         parm_opt_value = lp_parm_const_string( snum,
4391                                 local_parm_name, parm_opt, NULL);
4392                         if (parm_opt_value) {
4393                                 printf( "%s\n", parm_opt_value);
4394                                 result = True;
4395                         }
4396                 }
4397                 return result;
4398         }
4399
4400         /* check for a key and print the value */
4401         if (isGlobal) {
4402                 p_class = P_GLOBAL;
4403                 flag = FLAG_GLOBAL;
4404         } else
4405                 p_class = P_LOCAL;
4406
4407         for (i = 0; parm_table[i].label; i++) {
4408                 if (strwicmp(parm_table[i].label, parm_name) == 0 &&
4409                     (parm_table[i].p_class == p_class || parm_table[i].flags & flag) &&
4410                     parm_table[i].ptr &&
4411                     (*parm_table[i].label != '-') &&
4412                     (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) 
4413                 {
4414                         void *ptr;
4415
4416                         if (isGlobal) {
4417                                 ptr = parm_table[i].ptr;
4418                         } else {
4419                                 service * pService = ServicePtrs[snum];
4420                                 ptr = ((char *)pService) +
4421                                         PTR_DIFF(parm_table[i].ptr, &sDefault);
4422                         }
4423
4424                         print_parameter(&parm_table[i],
4425                                         ptr, f);
4426                         fprintf(f, "\n");
4427                         result = True;
4428                         break;
4429                 }
4430         }
4431
4432         return result;
4433 }
4434
4435 /***************************************************************************
4436  Return info about the requested parameter (given as a string).
4437  Return NULL when the string is not a valid parameter name.
4438 ***************************************************************************/
4439
4440 struct parm_struct *lp_get_parameter(const char *param_name)
4441 {
4442         int num = map_parameter(param_name);
4443
4444         if (num < 0) {
4445                 return NULL;
4446         }
4447
4448         return &parm_table[num];
4449 }
4450
4451 /***************************************************************************
4452  Return info about the next parameter in a service.
4453  snum==GLOBAL_SECTION_SNUM gives the globals.
4454  Return NULL when out of parameters.
4455 ***************************************************************************/
4456
4457 struct parm_struct *lp_next_parameter(int snum, int *i, int allparameters)
4458 {
4459         if (snum < 0) {
4460                 /* do the globals */
4461                 for (; parm_table[*i].label; (*i)++) {
4462                         if (parm_table[*i].p_class == P_SEPARATOR)
4463                                 return &parm_table[(*i)++];
4464
4465                         if (!parm_table[*i].ptr
4466                             || (*parm_table[*i].label == '-'))
4467                                 continue;
4468
4469                         if ((*i) > 0
4470                             && (parm_table[*i].ptr ==
4471                                 parm_table[(*i) - 1].ptr))
4472                                 continue;
4473                         
4474                         if (is_default(*i) && !allparameters)
4475                                 continue;
4476
4477                         return &parm_table[(*i)++];
4478                 }
4479         } else {
4480                 service *pService = ServicePtrs[snum];
4481
4482                 for (; parm_table[*i].label; (*i)++) {
4483                         if (parm_table[*i].p_class == P_SEPARATOR)
4484                                 return &parm_table[(*i)++];
4485
4486                         if (parm_table[*i].p_class == P_LOCAL &&
4487                             parm_table[*i].ptr &&
4488                             (*parm_table[*i].label != '-') &&
4489                             ((*i) == 0 ||
4490                              (parm_table[*i].ptr !=
4491                               parm_table[(*i) - 1].ptr)))
4492                         {
4493                                 int pdiff =
4494                                         PTR_DIFF(parm_table[*i].ptr,
4495                                                  &sDefault);
4496
4497                                 if (allparameters ||
4498                                     !equal_parameter(parm_table[*i].type,
4499                                                      ((char *)pService) +
4500                                                      pdiff,
4501                                                      ((char *)&sDefault) +
4502                                                      pdiff))
4503                                 {
4504                                         return &parm_table[(*i)++];
4505                                 }
4506                         }
4507                 }
4508         }
4509
4510         return NULL;
4511 }
4512
4513
4514 #if 0
4515 /***************************************************************************
4516  Display the contents of a single copy structure.
4517 ***************************************************************************/
4518 static void dump_copy_map(bool *pcopymap)
4519 {
4520         int i;
4521         if (!pcopymap)
4522                 return;
4523
4524         printf("\n\tNon-Copied parameters:\n");
4525
4526         for (i = 0; parm_table[i].label; i++)
4527                 if (parm_table[i].p_class == P_LOCAL &&
4528                     parm_table[i].ptr && !pcopymap[i] &&
4529                     (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr)))
4530                 {
4531                         printf("\t\t%s\n", parm_table[i].label);
4532                 }
4533 }
4534 #endif
4535
4536 /***************************************************************************
4537  Return TRUE if the passed service number is within range.
4538 ***************************************************************************/
4539
4540 bool lp_snum_ok(int iService)
4541 {
4542         return (LP_SNUM_OK(iService) && ServicePtrs[iService]->bAvailable);
4543 }
4544
4545 /***************************************************************************
4546  Auto-load some home services.
4547 ***************************************************************************/
4548
4549 static void lp_add_auto_services(char *str)
4550 {
4551         char *s;
4552         char *p;
4553         int homes;
4554         char *saveptr;
4555
4556         if (!str)
4557                 return;
4558
4559         s = SMB_STRDUP(str);
4560         if (!s)
4561                 return;
4562
4563         homes = lp_servicenumber(HOMES_NAME);
4564
4565         for (p = strtok_r(s, LIST_SEP, &saveptr); p;
4566              p = strtok_r(NULL, LIST_SEP, &saveptr)) {
4567                 char *home;
4568
4569                 if (lp_servicenumber(p) >= 0)
4570                         continue;
4571
4572                 home = get_user_home_dir(talloc_tos(), p);
4573
4574                 if (home && homes >= 0)
4575                         lp_add_home(p, homes, p, home);
4576
4577                 TALLOC_FREE(home);
4578         }
4579         SAFE_FREE(s);
4580 }
4581
4582 /***************************************************************************
4583  Auto-load one printer.
4584 ***************************************************************************/
4585
4586 void lp_add_one_printer(char *name, char *comment)
4587 {
4588         int printers = lp_servicenumber(PRINTERS_NAME);
4589         int i;
4590
4591         if (lp_servicenumber(name) < 0) {
4592                 lp_add_printer(name, printers);
4593                 if ((i = lp_servicenumber(name)) >= 0) {
4594                         string_set(&ServicePtrs[i]->comment, comment);
4595                         ServicePtrs[i]->autoloaded = True;
4596                 }
4597         }
4598 }
4599
4600 /***************************************************************************
4601  Have we loaded a services file yet?
4602 ***************************************************************************/
4603
4604 bool lp_loaded(void)
4605 {
4606         return (bLoaded);
4607 }
4608
4609 /***************************************************************************
4610  Unload unused services.
4611 ***************************************************************************/
4612
4613 void lp_killunused(bool (*snumused) (int))
4614 {
4615         int i;
4616         for (i = 0; i < iNumServices; i++) {
4617                 if (!VALID(i))
4618                         continue;
4619
4620                 /* don't kill autoloaded or usershare services */
4621                 if ( ServicePtrs[i]->autoloaded ||
4622                                 ServicePtrs[i]->usershare == USERSHARE_VALID) {
4623                         continue;
4624                 }
4625
4626                 if (!snumused || !snumused(i)) {
4627                         free_service_byindex(i);
4628                 }
4629         }
4630 }
4631
4632 /***************************************************************************
4633  Unload a service.
4634 ***************************************************************************/
4635
4636 void lp_killservice(int iServiceIn)
4637 {
4638         if (VALID(iServiceIn)) {
4639                 free_service_byindex(iServiceIn);
4640         }
4641 }
4642
4643 /***************************************************************************
4644  Save the curent values of all global and sDefault parameters into the 
4645  defaults union. This allows swat and testparm to show only the
4646  changed (ie. non-default) parameters.
4647 ***************************************************************************/
4648
4649 static void lp_save_defaults(void)
4650 {
4651         int i;
4652         for (i = 0; parm_table[i].label; i++) {
4653                 if (i > 0 && parm_table[i].ptr == parm_table[i - 1].ptr)
4654                         continue;
4655                 switch (parm_table[i].type) {
4656                         case P_LIST:
4657                                 str_list_copy(
4658                                         NULL, &(parm_table[i].def.lvalue),
4659                                         *(const char ***)parm_table[i].ptr);
4660                                 break;
4661                         case P_STRING:
4662                         case P_USTRING:
4663                                 if (parm_table[i].ptr) {
4664                                         parm_table[i].def.svalue = SMB_STRDUP(*(char **)parm_table[i].ptr);
4665                                 } else {
4666                                         parm_table[i].def.svalue = NULL;
4667                                 }
4668                                 break;
4669                         case P_BOOL:
4670                         case P_BOOLREV:
4671                                 parm_table[i].def.bvalue =
4672                                         *(bool *)parm_table[i].ptr;
4673                                 break;
4674                         case P_CHAR:
4675                                 parm_table[i].def.cvalue =
4676                                         *(char *)parm_table[i].ptr;
4677                                 break;
4678                         case P_INTEGER:
4679                         case P_OCTAL:
4680                         case P_ENUM:
4681                                 parm_table[i].def.ivalue =
4682                                         *(int *)parm_table[i].ptr;
4683                                 break;
4684                         case P_SEP:
4685                                 break;
4686                 }
4687         }
4688         defaults_saved = True;
4689 }
4690
4691 /*******************************************************************
4692  Set the server type we will announce as via nmbd.
4693 ********************************************************************/
4694
4695 static const struct srv_role_tab {
4696         uint32 role;
4697         const char *role_str;
4698 } srv_role_tab [] = {
4699         { ROLE_STANDALONE, "ROLE_STANDALONE" },
4700         { ROLE_DOMAIN_MEMBER, "ROLE_DOMAIN_MEMBER" },
4701         { ROLE_DOMAIN_BDC, "ROLE_DOMAIN_BDC" },
4702         { ROLE_DOMAIN_PDC, "ROLE_DOMAIN_PDC" },
4703         { 0, NULL }
4704 };
4705
4706 const char* server_role_str(uint32 role)
4707 {
4708         int i = 0;
4709         for (i=0; srv_role_tab[i].role_str; i++) {
4710                 if (role == srv_role_tab[i].role) {
4711                         return srv_role_tab[i].role_str;
4712                 }
4713         }
4714         return NULL;
4715 }
4716
4717 static void set_server_role(void)
4718 {
4719         server_role = ROLE_STANDALONE;
4720
4721         switch (lp_security()) {
4722                 case SEC_SHARE:
4723                         if (lp_domain_logons())
4724                                 DEBUG(0, ("Server's Role (logon server) conflicts with share-level security\n"));
4725                         break;
4726                 case SEC_SERVER:
4727                         if (lp_domain_logons())
4728                                 DEBUG(0, ("Server's Role (logon server) conflicts with server-level security\n"));
4729                         /* this used to be considered ROLE_DOMAIN_MEMBER but that's just wrong */
4730                         server_role = ROLE_STANDALONE;
4731                         break;
4732                 case SEC_DOMAIN:
4733                         if (lp_domain_logons()) {
4734                                 DEBUG(1, ("Server's Role (logon server) NOT ADVISED with domain-level security\n"));
4735                                 server_role = ROLE_DOMAIN_BDC;
4736                                 break;
4737                         }
4738                         server_role = ROLE_DOMAIN_MEMBER;
4739                         break;
4740                 case SEC_ADS:
4741                         if (lp_domain_logons()) {
4742                                 server_role = ROLE_DOMAIN_PDC;
4743                                 break;
4744                         }
4745                         server_role = ROLE_DOMAIN_MEMBER;
4746                         break;
4747                 case SEC_USER:
4748                         if (lp_domain_logons()) {
4749
4750                                 if (Globals.iDomainMaster) /* auto or yes */ 
4751                                         server_role = ROLE_DOMAIN_PDC;
4752                                 else
4753                                         server_role = ROLE_DOMAIN_BDC;
4754                         }
4755                         break;
4756                 default:
4757                         DEBUG(0, ("Server's Role undefined due to unknown security mode\n"));
4758                         break;
4759         }
4760
4761         DEBUG(10, ("set_server_role: role = %s\n", server_role_str(server_role)));
4762 }
4763
4764 /***********************************************************
4765  If we should send plaintext/LANMAN passwords in the clinet
4766 ************************************************************/
4767
4768 static void set_allowed_client_auth(void)
4769 {
4770         if (Globals.bClientNTLMv2Auth) {
4771                 Globals.bClientLanManAuth = False;
4772         }
4773         if (!Globals.bClientLanManAuth) {
4774                 Globals.bClientPlaintextAuth = False;
4775         }
4776 }
4777
4778 /***************************************************************************
4779  JRA.
4780  The following code allows smbd to read a user defined share file.
4781  Yes, this is my intent. Yes, I'm comfortable with that...
4782
4783  THE FOLLOWING IS SECURITY CRITICAL CODE.
4784
4785  It washes your clothes, it cleans your house, it guards you while you sleep...
4786  Do not f%^k with it....
4787 ***************************************************************************/
4788
4789 #define MAX_USERSHARE_FILE_SIZE (10*1024)
4790
4791 /***************************************************************************
4792  Check allowed stat state of a usershare file.
4793  Ensure we print out who is dicking with us so the admin can
4794  get their sorry ass fired.
4795 ***************************************************************************/
4796
4797 static bool check_usershare_stat(const char *fname, SMB_STRUCT_STAT *psbuf)
4798 {
4799         if (!S_ISREG(psbuf->st_mode)) {
4800                 DEBUG(0,("check_usershare_stat: file %s owned by uid %u is "
4801                         "not a regular file\n",
4802                         fname, (unsigned int)psbuf->st_uid ));
4803                 return False;
4804         }
4805
4806         /* Ensure this doesn't have the other write bit set. */
4807         if (psbuf->st_mode & S_IWOTH) {
4808                 DEBUG(0,("check_usershare_stat: file %s owned by uid %u allows "
4809                         "public write. Refusing to allow as a usershare file.\n",
4810                         fname, (unsigned int)psbuf->st_uid ));
4811                 return False;
4812         }
4813
4814         /* Should be 10k or less. */
4815         if (psbuf->st_size > MAX_USERSHARE_FILE_SIZE) {
4816                 DEBUG(0,("check_usershare_stat: file %s owned by uid %u is "
4817                         "too large (%u) to be a user share file.\n",
4818                         fname, (unsigned int)psbuf->st_uid,
4819                         (unsigned int)psbuf->st_size ));
4820                 return False;
4821         }
4822
4823         return True;
4824 }
4825
4826 /***************************************************************************
4827  Parse the contents of a usershare file.
4828 ***************************************************************************/
4829
4830 enum usershare_err parse_usershare_file(TALLOC_CTX *ctx,
4831                         SMB_STRUCT_STAT *psbuf,
4832                         const char *servicename,
4833                         int snum,
4834                         char **lines,
4835                         int numlines,
4836                         char **pp_sharepath,
4837                         char **pp_comment,
4838                         SEC_DESC **ppsd,
4839                         bool *pallow_guest)
4840 {
4841         const char **prefixallowlist = lp_usershare_prefix_allow_list();
4842         const char **prefixdenylist = lp_usershare_prefix_deny_list();
4843         int us_vers;
4844         SMB_STRUCT_DIR *dp;
4845         SMB_STRUCT_STAT sbuf;
4846         char *sharepath = NULL;
4847         char *comment = NULL;
4848
4849         *pp_sharepath = NULL;
4850         *pp_comment = NULL;
4851
4852         *pallow_guest = False;
4853
4854         if (numlines < 4) {
4855                 return USERSHARE_MALFORMED_FILE;
4856         }
4857
4858         if (strcmp(lines[0], "#VERSION 1") == 0) {
4859                 us_vers = 1;
4860         } else if (strcmp(lines[0], "#VERSION 2") == 0) {
4861                 us_vers = 2;
4862                 if (numlines < 5) {
4863                         return USERSHARE_MALFORMED_FILE;
4864                 }
4865         } else {
4866                 return USERSHARE_BAD_VERSION;
4867         }
4868
4869         if (strncmp(lines[1], "path=", 5) != 0) {
4870                 return USERSHARE_MALFORMED_PATH;
4871         }
4872
4873         sharepath = talloc_strdup(ctx, &lines[1][5]);
4874         if (!sharepath) {
4875                 return USERSHARE_POSIX_ERR;
4876         }
4877         trim_string(sharepath, " ", " ");
4878
4879         if (strncmp(lines[2], "comment=", 8) != 0) {
4880                 return USERSHARE_MALFORMED_COMMENT_DEF;
4881         }
4882
4883         comment = talloc_strdup(ctx, &lines[2][8]);
4884         if (!comment) {
4885                 return USERSHARE_POSIX_ERR;
4886         }
4887         trim_string(comment, " ", " ");
4888         trim_char(comment, '"', '"');
4889
4890         if (strncmp(lines[3], "usershare_acl=", 14) != 0) {
4891                 return USERSHARE_MALFORMED_ACL_DEF;
4892         }
4893
4894         if (!parse_usershare_acl(ctx, &lines[3][14], ppsd)) {
4895                 return USERSHARE_ACL_ERR;
4896         }
4897
4898         if (us_vers == 2) {
4899                 if (strncmp(lines[4], "guest_ok=", 9) != 0) {
4900                         return USERSHARE_MALFORMED_ACL_DEF;
4901                 }
4902                 if (lines[4][9] == 'y') {
4903                         *pallow_guest = True;
4904                 }
4905         }
4906
4907         if (snum != -1 && (strcmp(sharepath, ServicePtrs[snum]->szPath) == 0)) {
4908                 /* Path didn't change, no checks needed. */
4909                 *pp_sharepath = sharepath;
4910                 *pp_comment = comment;
4911                 return USERSHARE_OK;
4912         }
4913
4914         /* The path *must* be absolute. */
4915         if (sharepath[0] != '/') {
4916                 DEBUG(2,("parse_usershare_file: share %s: path %s is not an absolute path.\n",
4917                         servicename, sharepath));
4918                 return USERSHARE_PATH_NOT_ABSOLUTE;
4919         }
4920
4921         /* If there is a usershare prefix deny list ensure one of these paths
4922            doesn't match the start of the user given path. */
4923         if (prefixdenylist) {
4924                 int i;
4925                 for ( i=0; prefixdenylist[i]; i++ ) {
4926                         DEBUG(10,("parse_usershare_file: share %s : checking prefixdenylist[%d]='%s' against %s\n",
4927                                 servicename, i, prefixdenylist[i], sharepath ));
4928                         if (memcmp( sharepath, prefixdenylist[i], strlen(prefixdenylist[i])) == 0) {
4929                                 DEBUG(2,("parse_usershare_file: share %s path %s starts with one of the "
4930                                         "usershare prefix deny list entries.\n",
4931                                         servicename, sharepath));
4932                                 return USERSHARE_PATH_IS_DENIED;
4933                         }
4934                 }
4935         }
4936
4937         /* If there is a usershare prefix allow list ensure one of these paths
4938            does match the start of the user given path. */
4939
4940         if (prefixallowlist) {
4941                 int i;
4942                 for ( i=0; prefixallowlist[i]; i++ ) {
4943                         DEBUG(10,("parse_usershare_file: share %s checking prefixallowlist[%d]='%s' against %s\n",
4944                                 servicename, i, prefixallowlist[i], sharepath ));
4945                         if (memcmp( sharepath, prefixallowlist[i], strlen(prefixallowlist[i])) == 0) {
4946                                 break;
4947                         }
4948                 }
4949                 if (prefixallowlist[i] == NULL) {
4950                         DEBUG(2,("parse_usershare_file: share %s path %s doesn't start with one of the "
4951                                 "usershare prefix allow list entries.\n",
4952                                 servicename, sharepath));
4953                         return USERSHARE_PATH_NOT_ALLOWED;
4954                 }
4955         }
4956
4957         /* Ensure this is pointing to a directory. */
4958         dp = sys_opendir(sharepath);
4959
4960         if (!dp) {
4961                 DEBUG(2,("parse_usershare_file: share %s path %s is not a directory.\n",
4962                         servicename, sharepath));
4963                 return USERSHARE_PATH_NOT_DIRECTORY;
4964         }
4965
4966         /* Ensure the owner of the usershare file has permission to share
4967            this directory. */
4968
4969         if (sys_stat(sharepath, &sbuf) == -1) {
4970                 DEBUG(2,("parse_usershare_file: share %s : stat failed on path %s. %s\n",
4971                         servicename, sharepath, strerror(errno) ));
4972                 sys_closedir(dp);
4973                 return USERSHARE_POSIX_ERR;
4974         }
4975
4976         sys_closedir(dp);
4977
4978         if (!S_ISDIR(sbuf.st_mode)) {
4979                 DEBUG(2,("parse_usershare_file: share %s path %s is not a directory.\n",
4980                         servicename, sharepath ));
4981                 return USERSHARE_PATH_NOT_DIRECTORY;
4982         }
4983
4984         /* Check if sharing is restricted to owner-only. */
4985         /* psbuf is the stat of the usershare definition file,
4986            sbuf is the stat of the target directory to be shared. */
4987
4988         if (lp_usershare_owner_only()) {
4989                 /* root can share anything. */
4990                 if ((psbuf->st_uid != 0) && (sbuf.st_uid != psbuf->st_uid)) {
4991                         return USERSHARE_PATH_NOT_ALLOWED;
4992                 }
4993         }
4994
4995         *pp_sharepath = sharepath;
4996         *pp_comment = comment;
4997         return USERSHARE_OK;
4998 }
4999
5000 /***************************************************************************
5001  Deal with a usershare file.
5002  Returns:
5003         >= 0 - snum
5004         -1 - Bad name, invalid contents.
5005            - service name already existed and not a usershare, problem
5006             with permissions to share directory etc.
5007 ***************************************************************************/
5008
5009 static int process_usershare_file(const char *dir_name, const char *file_name, int snum_template)
5010 {
5011         SMB_STRUCT_STAT sbuf;
5012         SMB_STRUCT_STAT lsbuf;
5013         char *fname = NULL;
5014         char *sharepath = NULL;
5015         char *comment = NULL;
5016         fstring service_name;
5017         char **lines = NULL;
5018         int numlines = 0;
5019         int fd = -1;
5020         int iService = -1;
5021         TALLOC_CTX *ctx = NULL;
5022         SEC_DESC *psd = NULL;
5023         bool guest_ok = False;
5024
5025         /* Ensure share name doesn't contain invalid characters. */
5026         if (!validate_net_name(file_name, INVALID_SHARENAME_CHARS, strlen(file_name))) {
5027                 DEBUG(0,("process_usershare_file: share name %s contains "
5028                         "invalid characters (any of %s)\n",
5029                         file_name, INVALID_SHARENAME_CHARS ));
5030                 return -1;
5031         }
5032
5033         fstrcpy(service_name, file_name);
5034
5035         if (asprintf(&fname, "%s/%s", dir_name, file_name) < 0) {
5036         }
5037
5038         /* Minimize the race condition by doing an lstat before we
5039            open and fstat. Ensure this isn't a symlink link. */
5040
5041         if (sys_lstat(fname, &lsbuf) != 0) {
5042                 DEBUG(0,("process_usershare_file: stat of %s failed. %s\n",
5043                         fname, strerror(errno) ));
5044                 SAFE_FREE(fname);
5045                 return -1;
5046         }
5047
5048         /* This must be a regular file, not a symlink, directory or
5049            other strange filetype. */
5050         if (!check_usershare_stat(fname, &lsbuf)) {
5051                 SAFE_FREE(fname);
5052                 return -1;
5053         }
5054
5055         {
5056                 char *canon_name = canonicalize_servicename(service_name);
5057                 TDB_DATA data = dbwrap_fetch_bystring(
5058                         ServiceHash, canon_name, canon_name);
5059
5060                 iService = -1;
5061
5062                 if ((data.dptr != NULL) && (data.dsize == sizeof(iService))) {
5063                         iService = *(int *)data.dptr;
5064                 }
5065                 TALLOC_FREE(canon_name);
5066         }
5067
5068         if (iService != -1 && ServicePtrs[iService]->usershare_last_mod == lsbuf.st_mtime) {
5069                 /* Nothing changed - Mark valid and return. */
5070                 DEBUG(10,("process_usershare_file: service %s not changed.\n",
5071                         service_name ));
5072                 ServicePtrs[iService]->usershare = USERSHARE_VALID;
5073                 SAFE_FREE(fname);
5074                 return iService;
5075         }
5076
5077         /* Try and open the file read only - no symlinks allowed. */
5078 #ifdef O_NOFOLLOW
5079         fd = sys_open(fname, O_RDONLY|O_NOFOLLOW, 0);
5080 #else
5081         fd = sys_open(fname, O_RDONLY, 0);
5082 #endif
5083
5084         if (fd == -1) {
5085                 DEBUG(0,("process_usershare_file: unable to open %s. %s\n",
5086                         fname, strerror(errno) ));
5087                 SAFE_FREE(fname);
5088                 return -1;
5089         }
5090
5091         /* Now fstat to be *SURE* it's a regular file. */
5092         if (sys_fstat(fd, &sbuf) != 0) {
5093                 close(fd);
5094                 DEBUG(0,("process_usershare_file: fstat of %s failed. %s\n",
5095                         fname, strerror(errno) ));
5096                 SAFE_FREE(fname);
5097                 return -1;
5098         }
5099
5100         /* Is it the same dev/inode as was lstated ? */
5101         if (lsbuf.st_dev != sbuf.st_dev || lsbuf.st_ino != sbuf.st_ino) {
5102                 close(fd);
5103                 DEBUG(0,("process_usershare_file: fstat of %s is a different file from lstat. "
5104                         "Symlink spoofing going on ?\n", fname ));
5105                 SAFE_FREE(fname);
5106                 return -1;
5107         }
5108
5109         /* This must be a regular file, not a symlink, directory or
5110            other strange filetype. */
5111         if (!check_usershare_stat(fname, &sbuf)) {
5112                 SAFE_FREE(fname);
5113                 return -1;
5114         }
5115
5116         lines = fd_lines_load(fd, &numlines, MAX_USERSHARE_FILE_SIZE);
5117
5118         close(fd);
5119         if (lines == NULL) {
5120                 DEBUG(0,("process_usershare_file: loading file %s owned by %u failed.\n",
5121                         fname, (unsigned int)sbuf.st_uid ));
5122                 SAFE_FREE(fname);
5123                 return -1;
5124         }
5125
5126         SAFE_FREE(fname);
5127
5128         /* Should we allow printers to be shared... ? */
5129         ctx = talloc_init("usershare_sd_xctx");
5130         if (!ctx) {
5131                 file_lines_free(lines);
5132                 return 1;
5133         }
5134
5135         if (parse_usershare_file(ctx, &sbuf, service_name,
5136                         iService, lines, numlines, &sharepath,
5137                         &comment, &psd, &guest_ok) != USERSHARE_OK) {
5138                 talloc_destroy(ctx);
5139                 file_lines_free(lines);
5140                 return -1;
5141         }
5142
5143         file_lines_free(lines);
5144
5145         /* Everything ok - add the service possibly using a template. */
5146         if (iService < 0) {
5147                 const service *sp = &sDefault;
5148                 if (snum_template != -1) {
5149                         sp = ServicePtrs[snum_template];
5150                 }
5151
5152                 if ((iService = add_a_service(sp, service_name)) < 0) {
5153                         DEBUG(0, ("process_usershare_file: Failed to add "
5154                                 "new service %s\n", service_name));
5155                         talloc_destroy(ctx);
5156                         return -1;
5157                 }
5158
5159                 /* Read only is controlled by usershare ACL below. */
5160                 ServicePtrs[iService]->bRead_only = False;
5161         }
5162
5163         /* Write the ACL of the new/modified share. */
5164         if (!set_share_security(service_name, psd)) {
5165                  DEBUG(0, ("process_usershare_file: Failed to set share "
5166                         "security for user share %s\n",
5167                         service_name ));
5168                 lp_remove_service(iService);
5169                 talloc_destroy(ctx);
5170                 return -1;
5171         }
5172
5173         /* If from a template it may be marked invalid. */
5174         ServicePtrs[iService]->valid = True;
5175
5176         /* Set the service as a valid usershare. */
5177         ServicePtrs[iService]->usershare = USERSHARE_VALID;
5178
5179         /* Set guest access. */
5180         if (lp_usershare_allow_guests()) {
5181                 ServicePtrs[iService]->bGuest_ok = guest_ok;
5182         }
5183
5184         /* And note when it was loaded. */
5185         ServicePtrs[iService]->usershare_last_mod = sbuf.st_mtime;
5186         string_set(&ServicePtrs[iService]->szPath, sharepath);
5187         string_set(&ServicePtrs[iService]->comment, comment);
5188
5189         talloc_destroy(ctx);
5190
5191         return iService;
5192 }
5193
5194 /***************************************************************************
5195  Checks if a usershare entry has been modified since last load.
5196 ***************************************************************************/
5197
5198 static bool usershare_exists(int iService, time_t *last_mod)
5199 {
5200         SMB_STRUCT_STAT lsbuf;
5201         const char *usersharepath = Globals.szUsersharePath;
5202         char *fname;
5203
5204         if (asprintf(&fname, "%s/%s",
5205                                 usersharepath,
5206                                 ServicePtrs[iService]->szService) < 0) {
5207                 return false;
5208         }
5209
5210         if (sys_lstat(fname, &lsbuf) != 0) {
5211                 SAFE_FREE(fname);
5212                 return false;
5213         }
5214
5215         if (!S_ISREG(lsbuf.st_mode)) {
5216                 SAFE_FREE(fname);
5217                 return false;
5218         }
5219
5220         SAFE_FREE(fname);
5221         *last_mod = lsbuf.st_mtime;
5222         return true;
5223 }
5224
5225 /***************************************************************************
5226  Load a usershare service by name. Returns a valid servicenumber or -1.
5227 ***************************************************************************/
5228
5229 int load_usershare_service(const char *servicename)
5230 {
5231         SMB_STRUCT_STAT sbuf;
5232         const char *usersharepath = Globals.szUsersharePath;
5233         int max_user_shares = Globals.iUsershareMaxShares;
5234         int snum_template = -1;
5235
5236         if (*usersharepath == 0 ||  max_user_shares == 0) {
5237                 return -1;
5238         }
5239
5240         if (sys_stat(usersharepath, &sbuf) != 0) {
5241                 DEBUG(0,("load_usershare_service: stat of %s failed. %s\n",
5242                         usersharepath, strerror(errno) ));
5243                 return -1;
5244         }
5245
5246         if (!S_ISDIR(sbuf.st_mode)) {
5247                 DEBUG(0,("load_usershare_service: %s is not a directory.\n",
5248                         usersharepath ));
5249                 return -1;
5250         }
5251
5252         /*
5253          * This directory must be owned by root, and have the 't' bit set.
5254          * It also must not be writable by "other".
5255          */
5256
5257 #ifdef S_ISVTX
5258         if (sbuf.st_uid != 0 || !(sbuf.st_mode & S_ISVTX) || (sbuf.st_mode & S_IWOTH)) {
5259 #else
5260         if (sbuf.st_uid != 0 || (sbuf.st_mode & S_IWOTH)) {
5261 #endif
5262                 DEBUG(0,("load_usershare_service: directory %s is not owned by root "
5263                         "or does not have the sticky bit 't' set or is writable by anyone.\n",
5264                         usersharepath ));
5265                 return -1;
5266         }
5267
5268         /* Ensure the template share exists if it's set. */
5269         if (Globals.szUsershareTemplateShare[0]) {
5270                 /* We can't use lp_servicenumber here as we are recommending that
5271                    template shares have -valid=False set. */
5272                 for (snum_template = iNumServices - 1; snum_template >= 0; snum_template--) {
5273                         if (ServicePtrs[snum_template]->szService &&
5274                                         strequal(ServicePtrs[snum_template]->szService,
5275                                                 Globals.szUsershareTemplateShare)) {
5276                                 break;
5277                         }
5278                 }
5279
5280                 if (snum_template == -1) {
5281                         DEBUG(0,("load_usershare_service: usershare template share %s "
5282                                 "does not exist.\n",
5283                                 Globals.szUsershareTemplateShare ));
5284                         return -1;
5285                 }
5286         }
5287
5288         return process_usershare_file(usersharepath, servicename, snum_template);
5289 }
5290
5291 /***************************************************************************
5292  Load all user defined shares from the user share directory.
5293  We only do this if we're enumerating the share list.
5294  This is the function that can delete usershares that have
5295  been removed.
5296 ***************************************************************************/
5297
5298 int load_usershare_shares(void)
5299 {
5300         SMB_STRUCT_DIR *dp;
5301         SMB_STRUCT_STAT sbuf;
5302         SMB_STRUCT_DIRENT *de;
5303         int num_usershares = 0;
5304         int max_user_shares = Globals.iUsershareMaxShares;
5305         unsigned int num_dir_entries, num_bad_dir_entries, num_tmp_dir_entries;
5306         unsigned int allowed_bad_entries = ((2*max_user_shares)/10);
5307         unsigned int allowed_tmp_entries = ((2*max_user_shares)/10);
5308         int iService;
5309         int snum_template = -1;
5310         const char *usersharepath = Globals.szUsersharePath;
5311         int ret = lp_numservices();
5312
5313         if (max_user_shares == 0 || *usersharepath == '\0') {
5314                 return lp_numservices();
5315         }
5316
5317         if (sys_stat(usersharepath, &sbuf) != 0) {
5318                 DEBUG(0,("load_usershare_shares: stat of %s failed. %s\n",
5319                         usersharepath, strerror(errno) ));
5320                 return ret;
5321         }
5322
5323         /*
5324          * This directory must be owned by root, and have the 't' bit set.
5325          * It also must not be writable by "other".
5326          */
5327
5328 #ifdef S_ISVTX
5329         if (sbuf.st_uid != 0 || !(sbuf.st_mode & S_ISVTX) || (sbuf.st_mode & S_IWOTH)) {
5330 #else
5331         if (sbuf.st_uid != 0 || (sbuf.st_mode & S_IWOTH)) {
5332 #endif
5333                 DEBUG(0,("load_usershare_shares: directory %s is not owned by root "
5334                         "or does not have the sticky bit 't' set or is writable by anyone.\n",
5335                         usersharepath ));
5336                 return ret;
5337         }
5338
5339         /* Ensure the template share exists if it's set. */
5340         if (Globals.szUsershareTemplateShare[0]) {
5341                 /* We can't use lp_servicenumber here as we are recommending that
5342                    template shares have -valid=False set. */
5343                 for (snum_template = iNumServices - 1; snum_template >= 0; snum_template--) {
5344                         if (ServicePtrs[snum_template]->szService &&
5345                                         strequal(ServicePtrs[snum_template]->szService,
5346                                                 Globals.szUsershareTemplateShare)) {
5347                                 break;
5348                         }
5349                 }
5350
5351                 if (snum_template == -1) {
5352                         DEBUG(0,("load_usershare_shares: usershare template share %s "
5353                                 "does not exist.\n",
5354                                 Globals.szUsershareTemplateShare ));
5355                         return ret;
5356                 }
5357         }
5358
5359         /* Mark all existing usershares as pending delete. */
5360         for (iService = iNumServices - 1; iService >= 0; iService--) {
5361                 if (VALID(iService) && ServicePtrs[iService]->usershare) {
5362                         ServicePtrs[iService]->usershare = USERSHARE_PENDING_DELETE;
5363                 }
5364         }
5365
5366         dp = sys_opendir(usersharepath);
5367         if (!dp) {
5368                 DEBUG(0,("load_usershare_shares:: failed to open directory %s. %s\n",
5369                         usersharepath, strerror(errno) ));
5370                 return ret;
5371         }
5372
5373         for (num_dir_entries = 0, num_bad_dir_entries = 0, num_tmp_dir_entries = 0;
5374                         (de = sys_readdir(dp));
5375                         num_dir_entries++ ) {
5376                 int r;
5377                 const char *n = de->d_name;
5378
5379                 /* Ignore . and .. */
5380                 if (*n == '.') {
5381                         if ((n[1] == '\0') || (n[1] == '.' && n[2] == '\0')) {
5382                                 continue;
5383                         }
5384                 }
5385
5386                 if (n[0] == ':') {
5387                         /* Temporary file used when creating a share. */
5388                         num_tmp_dir_entries++;
5389                 }
5390
5391                 /* Allow 20% tmp entries. */
5392                 if (num_tmp_dir_entries > allowed_tmp_entries) {
5393                         DEBUG(0,("load_usershare_shares: too many temp entries (%u) "
5394                                 "in directory %s\n",
5395                                 num_tmp_dir_entries, usersharepath));
5396                         break;
5397                 }
5398
5399                 r = process_usershare_file(usersharepath, n, snum_template);
5400                 if (r == 0) {
5401                         /* Update the services count. */
5402                         num_usershares++;
5403                         if (num_usershares >= max_user_shares) {
5404                                 DEBUG(0,("load_usershare_shares: max user shares reached "
5405                                         "on file %s in directory %s\n",
5406                                         n, usersharepath ));
5407                                 break;
5408                         }
5409                 } else if (r == -1) {
5410                         num_bad_dir_entries++;
5411                 }
5412
5413                 /* Allow 20% bad entries. */
5414                 if (num_bad_dir_entries > allowed_bad_entries) {
5415                         DEBUG(0,("load_usershare_shares: too many bad entries (%u) "
5416                                 "in directory %s\n",
5417                                 num_bad_dir_entries, usersharepath));
5418                         break;
5419                 }
5420
5421                 /* Allow 20% bad entries. */
5422                 if (num_dir_entries > max_user_shares + allowed_bad_entries) {
5423                         DEBUG(0,("load_usershare_shares: too many total entries (%u) "
5424                         "in directory %s\n",
5425                         num_dir_entries, usersharepath));
5426                         break;
5427                 }
5428         }
5429
5430         sys_closedir(dp);
5431
5432         /* Sweep through and delete any non-refreshed usershares that are
5433            not currently in use. */
5434         for (iService = iNumServices - 1; iService >= 0; iService--) {
5435                 if (VALID(iService) && (ServicePtrs[iService]->usershare == USERSHARE_PENDING_DELETE)) {
5436                         if (conn_snum_used(iService)) {
5437                                 continue;
5438                         }
5439                         /* Remove from the share ACL db. */
5440                         DEBUG(10,("load_usershare_shares: Removing deleted usershare %s\n",
5441                                 lp_servicename(iService) ));
5442                         delete_share_security(lp_servicename(iService));
5443                         free_service_byindex(iService);
5444                 }
5445         }
5446
5447         return lp_numservices();
5448 }
5449
5450 /********************************************************
5451  Destroy global resources allocated in this file
5452 ********************************************************/
5453
5454 void gfree_loadparm(void)
5455 {
5456         struct file_lists *f;
5457         struct file_lists *next;
5458         int i;
5459
5460         /* Free the file lists */
5461
5462         f = file_lists;
5463         while( f ) {
5464                 next = f->next;
5465                 SAFE_FREE( f->name );
5466                 SAFE_FREE( f->subfname );
5467                 SAFE_FREE( f );
5468                 f = next;
5469         }
5470
5471         /* Free resources allocated to services */
5472
5473         for ( i = 0; i < iNumServices; i++ ) {
5474                 if ( VALID(i) ) {
5475                         free_service_byindex(i);
5476                 }
5477         }
5478
5479         SAFE_FREE( ServicePtrs );
5480         iNumServices = 0;
5481
5482         /* Now release all resources allocated to global
5483            parameters and the default service */
5484
5485         for (i = 0; parm_table[i].label; i++) 
5486         {
5487                 if ( parm_table[i].type == P_STRING 
5488                         || parm_table[i].type == P_USTRING ) 
5489                 {
5490                         string_free( (char**)parm_table[i].ptr );
5491                 }
5492                 else if (parm_table[i].type == P_LIST) {
5493                         TALLOC_FREE( *((char***)parm_table[i].ptr) );
5494                 }
5495         }
5496 }
5497
5498 /***************************************************************************
5499  Load the services array from the services file. Return True on success, 
5500  False on failure.
5501 ***************************************************************************/
5502
5503 bool lp_load(const char *pszFname,
5504              bool global_only,
5505              bool save_defaults,
5506              bool add_ipc,
5507              bool initialize_globals)
5508 {
5509         char *n2 = NULL;
5510         bool bRetval;
5511         param_opt_struct *data, *pdata;
5512
5513         bRetval = False;
5514
5515         DEBUG(3, ("lp_load: refreshing parameters\n"));
5516
5517         bInGlobalSection = True;
5518         bGlobalOnly = global_only;
5519
5520         init_globals(! initialize_globals);
5521         debug_init();
5522
5523         if (save_defaults) {
5524                 init_locals();
5525                 lp_save_defaults();
5526         }
5527
5528         if (Globals.param_opt != NULL) {
5529                 data = Globals.param_opt;
5530                 while (data) {
5531                         string_free(&data->key);
5532                         string_free(&data->value);
5533                         TALLOC_FREE(data->list);
5534                         pdata = data->next;
5535                         SAFE_FREE(data);
5536                         data = pdata;
5537                 }
5538                 Globals.param_opt = NULL;
5539         }
5540
5541         if (lp_config_backend() == CONFIG_BACKEND_FILE) {
5542                 n2 = alloc_sub_basic(get_current_username(),
5543                                         current_user_info.domain,
5544                                         pszFname);
5545                 if (!n2) {
5546                         smb_panic("lp_load: out of memory");
5547                 }
5548
5549                 add_to_file_list(pszFname, n2);
5550
5551                 /* We get sections first, so have to start 'behind' to make up */
5552                 iServiceIndex = -1;
5553                 bRetval = pm_process(n2, do_section, do_parameter);
5554                 SAFE_FREE(n2);
5555
5556                 /* finish up the last section */
5557                 DEBUG(4, ("pm_process() returned %s\n", BOOLSTR(bRetval)));
5558                 if (bRetval) {
5559                         if (iServiceIndex >= 0) {
5560                                 bRetval = service_ok(iServiceIndex);
5561                         }
5562                 }
5563
5564                 if (lp_config_backend() == CONFIG_BACKEND_REGISTRY) {
5565                         /*
5566                          * We need to use this extra global variable here to
5567                          * survive restart: init_globals usese this as a default
5568                          * for ConfigBackend. Otherwise, init_globals would
5569                          *  send us into an endless loop here.
5570                          */
5571                         config_backend = CONFIG_BACKEND_REGISTRY;
5572                         /* start over */
5573                         init_globals(false);
5574                         return lp_load(pszFname, global_only, save_defaults,
5575                                        add_ipc, initialize_globals);
5576                 }
5577         } else if (lp_config_backend() == CONFIG_BACKEND_REGISTRY) {
5578                 bRetval = process_registry_globals(do_parameter);
5579         } else {
5580                 DEBUG(0, ("Illegal config  backend given: %d\n",
5581                           lp_config_backend()));
5582                 bRetval = false;
5583         }
5584
5585         lp_add_auto_services(lp_auto_services());
5586
5587         if (add_ipc) {
5588                 /* When 'restrict anonymous = 2' guest connections to ipc$
5589                    are denied */
5590                 lp_add_ipc("IPC$", (lp_restrict_anonymous() < 2));
5591                 if ( lp_enable_asu_support() ) {
5592                         lp_add_ipc("ADMIN$", false);
5593                 }
5594         }
5595
5596         set_server_role();
5597         set_default_server_announce_type();
5598         set_allowed_client_auth();
5599
5600         bLoaded = True;
5601
5602         /* Now we check bWINSsupport and set szWINSserver to 127.0.0.1 */
5603         /* if bWINSsupport is true and we are in the client            */
5604         if (in_client && Globals.bWINSsupport) {
5605                 lp_do_parameter(GLOBAL_SECTION_SNUM, "wins server", "127.0.0.1");
5606         }
5607
5608         init_iconv();
5609
5610         return (bRetval);
5611 }
5612
5613 /***************************************************************************
5614  Reset the max number of services.
5615 ***************************************************************************/
5616
5617 void lp_resetnumservices(void)
5618 {
5619         iNumServices = 0;
5620 }
5621
5622 /***************************************************************************
5623  Return the max number of services.
5624 ***************************************************************************/
5625
5626 int lp_numservices(void)
5627 {
5628         return (iNumServices);
5629 }
5630
5631 /***************************************************************************
5632 Display the contents of the services array in human-readable form.
5633 ***************************************************************************/
5634
5635 void lp_dump(FILE *f, bool show_defaults, int maxtoprint)
5636 {
5637         int iService;
5638
5639         if (show_defaults)
5640                 defaults_saved = False;
5641
5642         dump_globals(f);
5643
5644         dump_a_service(&sDefault, f);
5645
5646         for (iService = 0; iService < maxtoprint; iService++) {
5647                 fprintf(f,"\n");
5648                 lp_dump_one(f, show_defaults, iService);
5649         }
5650 }
5651
5652 /***************************************************************************
5653 Display the contents of one service in human-readable form.
5654 ***************************************************************************/
5655
5656 void lp_dump_one(FILE * f, bool show_defaults, int snum)
5657 {
5658         if (VALID(snum)) {
5659                 if (ServicePtrs[snum]->szService[0] == '\0')
5660                         return;
5661                 dump_a_service(ServicePtrs[snum], f);
5662         }
5663 }
5664
5665 /***************************************************************************
5666 Return the number of the service with the given name, or -1 if it doesn't
5667 exist. Note that this is a DIFFERENT ANIMAL from the internal function
5668 getservicebyname()! This works ONLY if all services have been loaded, and
5669 does not copy the found service.
5670 ***************************************************************************/
5671
5672 int lp_servicenumber(const char *pszServiceName)
5673 {
5674         int iService;
5675         fstring serviceName;
5676         
5677         if (!pszServiceName) {
5678                 return GLOBAL_SECTION_SNUM;
5679         }
5680         
5681         for (iService = iNumServices - 1; iService >= 0; iService--) {
5682                 if (VALID(iService) && ServicePtrs[iService]->szService) {
5683                         /*
5684                          * The substitution here is used to support %U is
5685                          * service names
5686                          */
5687                         fstrcpy(serviceName, ServicePtrs[iService]->szService);
5688                         standard_sub_basic(get_current_username(),
5689                                            current_user_info.domain,
5690                                            serviceName,sizeof(serviceName));
5691                         if (strequal(serviceName, pszServiceName)) {
5692                                 break;
5693                         }
5694                 }
5695         }
5696
5697         if (iService >= 0 && ServicePtrs[iService]->usershare == USERSHARE_VALID) {
5698                 time_t last_mod;
5699
5700                 if (!usershare_exists(iService, &last_mod)) {
5701                         /* Remove the share security tdb entry for it. */
5702                         delete_share_security(lp_servicename(iService));
5703                         /* Remove it from the array. */
5704                         free_service_byindex(iService);
5705                         /* Doesn't exist anymore. */
5706                         return GLOBAL_SECTION_SNUM;
5707                 }
5708
5709                 /* Has it been modified ? If so delete and reload. */
5710                 if (ServicePtrs[iService]->usershare_last_mod < last_mod) {
5711                         /* Remove it from the array. */
5712                         free_service_byindex(iService);
5713                         /* and now reload it. */
5714                         iService = load_usershare_service(pszServiceName);
5715                 }
5716         }
5717
5718         if (iService < 0) {
5719                 DEBUG(7,("lp_servicenumber: couldn't find %s\n", pszServiceName));
5720                 return GLOBAL_SECTION_SNUM;
5721         }
5722
5723         return (iService);
5724 }
5725
5726 bool share_defined(const char *service_name)
5727 {
5728         return (lp_servicenumber(service_name) != -1);
5729 }
5730
5731 struct share_params *get_share_params(TALLOC_CTX *mem_ctx,
5732                                       const char *sharename)
5733 {
5734         struct share_params *result;
5735         char *sname;
5736         int snum;
5737
5738         if (!(sname = SMB_STRDUP(sharename))) {
5739                 return NULL;
5740         }
5741
5742         snum = find_service(sname);
5743         SAFE_FREE(sname);
5744
5745         if (snum < 0) {
5746                 return NULL;
5747         }
5748
5749         if (!(result = TALLOC_P(mem_ctx, struct share_params))) {
5750                 DEBUG(0, ("talloc failed\n"));
5751                 return NULL;
5752         }
5753
5754         result->service = snum;
5755         return result;
5756 }
5757
5758 struct share_iterator *share_list_all(TALLOC_CTX *mem_ctx)
5759 {
5760         struct share_iterator *result;
5761
5762         if (!(result = TALLOC_P(mem_ctx, struct share_iterator))) {
5763                 DEBUG(0, ("talloc failed\n"));
5764                 return NULL;
5765         }
5766
5767         result->next_id = 0;
5768         return result;
5769 }
5770
5771 struct share_params *next_share(struct share_iterator *list)
5772 {
5773         struct share_params *result;
5774
5775         while (!lp_snum_ok(list->next_id) &&
5776                (list->next_id < lp_numservices())) {
5777                 list->next_id += 1;
5778         }
5779
5780         if (list->next_id >= lp_numservices()) {
5781                 return NULL;
5782         }
5783
5784         if (!(result = TALLOC_P(list, struct share_params))) {
5785                 DEBUG(0, ("talloc failed\n"));
5786                 return NULL;
5787         }
5788
5789         result->service = list->next_id;
5790         list->next_id += 1;
5791         return result;
5792 }
5793
5794 struct share_params *next_printer(struct share_iterator *list)
5795 {
5796         struct share_params *result;
5797
5798         while ((result = next_share(list)) != NULL) {
5799                 if (lp_print_ok(result->service)) {
5800                         break;
5801                 }
5802         }
5803         return result;
5804 }
5805
5806 /*
5807  * This is a hack for a transition period until we transformed all code from
5808  * service numbers to struct share_params.
5809  */
5810
5811 struct share_params *snum2params_static(int snum)
5812 {
5813         static struct share_params result;
5814         result.service = snum;
5815         return &result;
5816 }
5817
5818 /*******************************************************************
5819  A useful volume label function. 
5820 ********************************************************************/
5821
5822 const char *volume_label(int snum)
5823 {
5824         char *ret;
5825         const char *label = lp_volume(snum);
5826         if (!*label) {
5827                 label = lp_servicename(snum);
5828         }
5829                 
5830         /* This returns a 33 byte guarenteed null terminated string. */
5831         ret = talloc_strndup(talloc_tos(), label, 32);
5832         if (!ret) {
5833                 return "";
5834         }               
5835         return ret;
5836 }
5837
5838 /*******************************************************************
5839  Set the server type we will announce as via nmbd.
5840 ********************************************************************/
5841
5842 static void set_default_server_announce_type(void)
5843 {
5844         default_server_announce = 0;
5845         default_server_announce |= SV_TYPE_WORKSTATION;
5846         default_server_announce |= SV_TYPE_SERVER;
5847         default_server_announce |= SV_TYPE_SERVER_UNIX;
5848
5849         /* note that the flag should be set only if we have a 
5850            printer service but nmbd doesn't actually load the 
5851            services so we can't tell   --jerry */
5852
5853         default_server_announce |= SV_TYPE_PRINTQ_SERVER;
5854
5855         switch (lp_announce_as()) {
5856                 case ANNOUNCE_AS_NT_SERVER:
5857                         default_server_announce |= SV_TYPE_SERVER_NT;
5858                         /* fall through... */
5859                 case ANNOUNCE_AS_NT_WORKSTATION:
5860                         default_server_announce |= SV_TYPE_NT;
5861                         break;
5862                 case ANNOUNCE_AS_WIN95:
5863                         default_server_announce |= SV_TYPE_WIN95_PLUS;
5864                         break;
5865                 case ANNOUNCE_AS_WFW:
5866                         default_server_announce |= SV_TYPE_WFW;
5867                         break;
5868                 default:
5869                         break;
5870         }
5871
5872         switch (lp_server_role()) {
5873                 case ROLE_DOMAIN_MEMBER:
5874                         default_server_announce |= SV_TYPE_DOMAIN_MEMBER;
5875                         break;
5876                 case ROLE_DOMAIN_PDC:
5877                         default_server_announce |= SV_TYPE_DOMAIN_CTRL;
5878                         break;
5879                 case ROLE_DOMAIN_BDC:
5880                         default_server_announce |= SV_TYPE_DOMAIN_BAKCTRL;
5881                         break;
5882                 case ROLE_STANDALONE:
5883                 default:
5884                         break;
5885         }
5886         if (lp_time_server())
5887                 default_server_announce |= SV_TYPE_TIME_SOURCE;
5888
5889         if (lp_host_msdfs())
5890                 default_server_announce |= SV_TYPE_DFS_SERVER;
5891 }
5892
5893 /***********************************************************
5894  returns role of Samba server
5895 ************************************************************/
5896
5897 int lp_server_role(void)
5898 {
5899         return server_role;
5900 }
5901
5902 /***********************************************************
5903  If we are PDC then prefer us as DMB
5904 ************************************************************/
5905
5906 bool lp_domain_master(void)
5907 {
5908         if (Globals.iDomainMaster == Auto)
5909                 return (lp_server_role() == ROLE_DOMAIN_PDC);
5910
5911         return (bool)Globals.iDomainMaster;
5912 }
5913
5914 /***********************************************************
5915  If we are DMB then prefer us as LMB
5916 ************************************************************/
5917
5918 bool lp_preferred_master(void)
5919 {
5920         if (Globals.iPreferredMaster == Auto)
5921                 return (lp_local_master() && lp_domain_master());
5922
5923         return (bool)Globals.iPreferredMaster;
5924 }
5925
5926 /*******************************************************************
5927  Remove a service.
5928 ********************************************************************/
5929
5930 void lp_remove_service(int snum)
5931 {
5932         ServicePtrs[snum]->valid = False;
5933         invalid_services[num_invalid_services++] = snum;
5934 }
5935
5936 /*******************************************************************
5937  Copy a service.
5938 ********************************************************************/
5939
5940 void lp_copy_service(int snum, const char *new_name)
5941 {
5942         do_section(new_name);
5943         if (snum >= 0) {
5944                 snum = lp_servicenumber(new_name);
5945                 if (snum >= 0)
5946                         lp_do_parameter(snum, "copy", lp_servicename(snum));
5947         }
5948 }
5949
5950
5951 /*******************************************************************
5952  Get the default server type we will announce as via nmbd.
5953 ********************************************************************/
5954
5955 int lp_default_server_announce(void)
5956 {
5957         return default_server_announce;
5958 }
5959
5960 /*******************************************************************
5961  Split the announce version into major and minor numbers.
5962 ********************************************************************/
5963
5964 int lp_major_announce_version(void)
5965 {
5966         static bool got_major = False;
5967         static int major_version = DEFAULT_MAJOR_VERSION;
5968         char *vers;
5969         char *p;
5970
5971         if (got_major)
5972                 return major_version;
5973
5974         got_major = True;
5975         if ((vers = lp_announce_version()) == NULL)
5976                 return major_version;
5977
5978         if ((p = strchr_m(vers, '.')) == 0)
5979                 return major_version;
5980
5981         *p = '\0';
5982         major_version = atoi(vers);
5983         return major_version;
5984 }
5985
5986 int lp_minor_announce_version(void)
5987 {
5988         static bool got_minor = False;
5989         static int minor_version = DEFAULT_MINOR_VERSION;
5990         char *vers;
5991         char *p;
5992
5993         if (got_minor)
5994                 return minor_version;
5995
5996         got_minor = True;
5997         if ((vers = lp_announce_version()) == NULL)
5998                 return minor_version;
5999
6000         if ((p = strchr_m(vers, '.')) == 0)
6001                 return minor_version;
6002
6003         p++;
6004         minor_version = atoi(p);
6005         return minor_version;
6006 }
6007
6008 /***********************************************************
6009  Set the global name resolution order (used in smbclient).
6010 ************************************************************/
6011
6012 void lp_set_name_resolve_order(const char *new_order)
6013 {
6014         string_set(&Globals.szNameResolveOrder, new_order);
6015 }
6016
6017 const char *lp_printername(int snum)
6018 {
6019         const char *ret = _lp_printername(snum);
6020         if (ret == NULL || (ret != NULL && *ret == '\0'))
6021                 ret = lp_const_servicename(snum);
6022
6023         return ret;
6024 }
6025
6026
6027 /***********************************************************
6028  Allow daemons such as winbindd to fix their logfile name.
6029 ************************************************************/
6030
6031 void lp_set_logfile(const char *name)
6032 {
6033         string_set(&Globals.szLogFile, name);
6034         debug_set_logfile(name);
6035 }
6036
6037 /*******************************************************************
6038  Return the max print jobs per queue.
6039 ********************************************************************/
6040
6041 int lp_maxprintjobs(int snum)
6042 {
6043         int maxjobs = LP_SNUM_OK(snum) ? ServicePtrs[snum]->iMaxPrintJobs : sDefault.iMaxPrintJobs;
6044         if (maxjobs <= 0 || maxjobs >= PRINT_MAX_JOBID)
6045                 maxjobs = PRINT_MAX_JOBID - 1;
6046
6047         return maxjobs;
6048 }
6049
6050 const char *lp_printcapname(void)
6051 {
6052         if ((Globals.szPrintcapname != NULL) &&
6053             (Globals.szPrintcapname[0] != '\0'))
6054                 return Globals.szPrintcapname;
6055
6056         if (sDefault.iPrinting == PRINT_CUPS) {
6057 #ifdef HAVE_CUPS
6058                 return "cups";
6059 #else
6060                 return "lpstat";
6061 #endif
6062         }
6063
6064         if (sDefault.iPrinting == PRINT_BSD)
6065                 return "/etc/printcap";
6066
6067         return PRINTCAP_NAME;
6068 }
6069
6070 /*******************************************************************
6071  Ensure we don't use sendfile if server smb signing is active.
6072 ********************************************************************/
6073
6074 static uint32 spoolss_state;
6075
6076 bool lp_disable_spoolss( void )
6077 {
6078         if ( spoolss_state == SVCCTL_STATE_UNKNOWN )
6079                 spoolss_state = _lp_disable_spoolss() ? SVCCTL_STOPPED : SVCCTL_RUNNING;
6080
6081         return spoolss_state == SVCCTL_STOPPED ? True : False;
6082 }
6083
6084 void lp_set_spoolss_state( uint32 state )
6085 {
6086         SMB_ASSERT( (state == SVCCTL_STOPPED) || (state == SVCCTL_RUNNING) );
6087
6088         spoolss_state = state;
6089 }
6090
6091 uint32 lp_get_spoolss_state( void )
6092 {
6093         return lp_disable_spoolss() ? SVCCTL_STOPPED : SVCCTL_RUNNING;
6094 }
6095
6096 /*******************************************************************
6097  Ensure we don't use sendfile if server smb signing is active.
6098 ********************************************************************/
6099
6100 bool lp_use_sendfile(int snum)
6101 {
6102         /* Using sendfile blows the brains out of any DOS or Win9x TCP stack... JRA. */
6103         if (Protocol < PROTOCOL_NT1) {
6104                 return False;
6105         }
6106         return (_lp_use_sendfile(snum) &&
6107                         (get_remote_arch() != RA_WIN95) &&
6108                         !srv_is_signing_active());
6109 }
6110
6111 /*******************************************************************
6112  Turn off sendfile if we find the underlying OS doesn't support it.
6113 ********************************************************************/
6114
6115 void set_use_sendfile(int snum, bool val)
6116 {
6117         if (LP_SNUM_OK(snum))
6118                 ServicePtrs[snum]->bUseSendfile = val;
6119         else
6120                 sDefault.bUseSendfile = val;
6121 }
6122
6123 /*******************************************************************
6124  Turn off storing DOS attributes if this share doesn't support it.
6125 ********************************************************************/
6126
6127 void set_store_dos_attributes(int snum, bool val)
6128 {
6129         if (!LP_SNUM_OK(snum))
6130                 return;
6131         ServicePtrs[(snum)]->bStoreDosAttributes = val;
6132 }
6133
6134 void lp_set_mangling_method(const char *new_method)
6135 {
6136         string_set(&Globals.szManglingMethod, new_method);
6137 }
6138
6139 /*******************************************************************
6140  Global state for POSIX pathname processing.
6141 ********************************************************************/
6142
6143 static bool posix_pathnames;
6144
6145 bool lp_posix_pathnames(void)
6146 {
6147         return posix_pathnames;
6148 }
6149
6150 /*******************************************************************
6151  Change everything needed to ensure POSIX pathname processing (currently
6152  not much).
6153 ********************************************************************/
6154
6155 void lp_set_posix_pathnames(void)
6156 {
6157         posix_pathnames = True;
6158 }
6159
6160 /*******************************************************************
6161  Global state for POSIX lock processing - CIFS unix extensions.
6162 ********************************************************************/
6163
6164 bool posix_default_lock_was_set;
6165 static enum brl_flavour posix_cifsx_locktype; /* By default 0 == WINDOWS_LOCK */
6166
6167 enum brl_flavour lp_posix_cifsu_locktype(files_struct *fsp)
6168 {
6169         if (posix_default_lock_was_set) {
6170                 return posix_cifsx_locktype;
6171         } else {
6172                 return fsp->posix_open ? POSIX_LOCK : WINDOWS_LOCK;
6173         }
6174 }
6175
6176 /*******************************************************************
6177 ********************************************************************/
6178
6179 void lp_set_posix_default_cifsx_readwrite_locktype(enum brl_flavour val)
6180 {
6181         posix_default_lock_was_set = True;
6182         posix_cifsx_locktype = val;
6183 }
6184
6185 int lp_min_receive_file_size(void)
6186 {
6187         if (Globals.iminreceivefile < 0) {
6188                 return 0;
6189         }
6190         return MIN(Globals.iminreceivefile, BUFFER_SIZE);
6191 }