Copy recent spoolss IDL from samba4 into our tree.
[gd/samba/.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                 if (conf_ctx == NULL) {
3494                         WERROR werr;
3495                         werr = libnet_conf_open(NULL, &conf_ctx);
3496                         if (!W_ERROR_IS_OK(werr)) {
3497                                 DEBUG(0, ("error opening configuration: %s\n",
3498                                           dos_errstr(werr)));
3499                                 return false;
3500                         }
3501                 }
3502                 if (conf_last_seqnum !=
3503                     libnet_conf_get_seqnum(conf_ctx, NULL, NULL))
3504                 {
3505                         DEBUGADD(6, ("regdb seqnum changed: old = %lu, "
3506                                      "new = %lu\n", conf_last_seqnum,
3507                                      libnet_conf_get_seqnum(conf_ctx, NULL, NULL)));
3508                         return true;
3509                 } else {
3510                         /*
3511                          * Don't check files when config_backend is registry.
3512                          * Remove this to obtain checking of files even with
3513                          * registry config backend. That would enable switching
3514                          * off registry configuration by changing smb.conf even
3515                          * without restarting smbd.
3516                          */
3517                         return false;
3518                 }
3519         }
3520
3521         while (f) {
3522                 char *n2 = NULL;
3523                 time_t mod_time;
3524
3525                 n2 = alloc_sub_basic(get_current_username(),
3526                                     current_user_info.domain,
3527                                     f->name);
3528                 if (!n2) {
3529                         return false;
3530                 }
3531                 DEBUGADD(6, ("file %s -> %s  last mod_time: %s\n",
3532                              f->name, n2, ctime(&f->modtime)));
3533
3534                 mod_time = file_modtime(n2);
3535
3536                 if (mod_time && ((f->modtime != mod_time) || (f->subfname == NULL) || (strcmp(n2, f->subfname) != 0))) {
3537                         DEBUGADD(6,
3538                                  ("file %s modified: %s\n", n2,
3539                                   ctime(&mod_time)));
3540                         f->modtime = mod_time;
3541                         SAFE_FREE(f->subfname);
3542                         f->subfname = n2; /* Passing ownership of
3543                                              return from alloc_sub_basic
3544                                              above. */
3545                         return true;
3546                 }
3547                 SAFE_FREE(n2);
3548                 f = f->next;
3549         }
3550         return (False);
3551 }
3552
3553
3554 /***************************************************************************
3555  Run standard_sub_basic on netbios name... needed because global_myname
3556  is not accessed through any lp_ macro.
3557  Note: We must *NOT* use string_set() here as ptr points to global_myname.
3558 ***************************************************************************/
3559
3560 static bool handle_netbios_name(int snum, const char *pszParmValue, char **ptr)
3561 {
3562         bool ret;
3563         char *netbios_name = alloc_sub_basic(get_current_username(),
3564                                         current_user_info.domain,
3565                                         pszParmValue);
3566
3567         ret = set_global_myname(netbios_name);
3568         SAFE_FREE(netbios_name);
3569         string_set(&Globals.szNetbiosName,global_myname());
3570
3571         DEBUG(4, ("handle_netbios_name: set global_myname to: %s\n",
3572                global_myname()));
3573
3574         return ret;
3575 }
3576
3577 static bool handle_charset(int snum, const char *pszParmValue, char **ptr)
3578 {
3579         if (strcmp(*ptr, pszParmValue) != 0) {
3580                 string_set(ptr, pszParmValue);
3581                 init_iconv();
3582         }
3583         return True;
3584 }
3585
3586
3587
3588 static bool handle_workgroup(int snum, const char *pszParmValue, char **ptr)
3589 {
3590         bool ret;
3591         
3592         ret = set_global_myworkgroup(pszParmValue);
3593         string_set(&Globals.szWorkgroup,lp_workgroup());
3594         
3595         return ret;
3596 }
3597
3598 static bool handle_netbios_scope(int snum, const char *pszParmValue, char **ptr)
3599 {
3600         bool ret;
3601         
3602         ret = set_global_scope(pszParmValue);
3603         string_set(&Globals.szNetbiosScope,global_scope());
3604
3605         return ret;
3606 }
3607
3608 static bool handle_netbios_aliases(int snum, const char *pszParmValue, char **ptr)
3609 {
3610         TALLOC_FREE(Globals.szNetbiosAliases);
3611         Globals.szNetbiosAliases = str_list_make(NULL, pszParmValue, NULL);
3612         return set_netbios_aliases((const char **)Globals.szNetbiosAliases);
3613 }
3614
3615 /***************************************************************************
3616  Handle the include operation.
3617 ***************************************************************************/
3618
3619 static bool handle_include(int snum, const char *pszParmValue, char **ptr)
3620 {
3621         char *fname;
3622
3623         fname = alloc_sub_basic(get_current_username(),
3624                                 current_user_info.domain,
3625                                 pszParmValue);
3626
3627         add_to_file_list(pszParmValue, fname);
3628
3629         string_set(ptr, fname);
3630
3631         if (file_exist(fname, NULL)) {
3632                 bool ret = pm_process(fname, do_section, do_parameter);
3633                 SAFE_FREE(fname);
3634                 return ret;
3635         }
3636
3637         DEBUG(2, ("Can't find include file %s\n", fname));
3638         SAFE_FREE(fname);
3639         return false;
3640 }
3641
3642 /***************************************************************************
3643  Handle the interpretation of the copy parameter.
3644 ***************************************************************************/
3645
3646 static bool handle_copy(int snum, const char *pszParmValue, char **ptr)
3647 {
3648         bool bRetval;
3649         int iTemp;
3650         service serviceTemp;
3651
3652         string_set(ptr, pszParmValue);
3653
3654         init_service(&serviceTemp);
3655
3656         bRetval = False;
3657
3658         DEBUG(3, ("Copying service from service %s\n", pszParmValue));
3659
3660         if ((iTemp = getservicebyname(pszParmValue, &serviceTemp)) >= 0) {
3661                 if (iTemp == iServiceIndex) {
3662                         DEBUG(0, ("Can't copy service %s - unable to copy self!\n", pszParmValue));
3663                 } else {
3664                         copy_service(ServicePtrs[iServiceIndex],
3665                                      &serviceTemp,
3666                                      ServicePtrs[iServiceIndex]->copymap);
3667                         bRetval = True;
3668                 }
3669         } else {
3670                 DEBUG(0, ("Unable to copy service - source not found: %s\n", pszParmValue));
3671                 bRetval = False;
3672         }
3673
3674         free_service(&serviceTemp);
3675         return (bRetval);
3676 }
3677
3678 static bool handle_ldap_debug_level(int snum, const char *pszParmValue, char **ptr)
3679 {
3680         Globals.ldap_debug_level = lp_int(pszParmValue);
3681         init_ldap_debugging();
3682         return true;
3683 }
3684
3685 /***************************************************************************
3686  Handle idmap/non unix account uid and gid allocation parameters.  The format of these
3687  parameters is:
3688
3689  [global]
3690
3691         idmap uid = 1000-1999
3692         idmap gid = 700-899
3693
3694  We only do simple parsing checks here.  The strings are parsed into useful
3695  structures in the idmap daemon code.
3696
3697 ***************************************************************************/
3698
3699 /* Some lp_ routines to return idmap [ug]id information */
3700
3701 static uid_t idmap_uid_low, idmap_uid_high;
3702 static gid_t idmap_gid_low, idmap_gid_high;
3703
3704 bool lp_idmap_uid(uid_t *low, uid_t *high)
3705 {
3706         if (idmap_uid_low == 0 || idmap_uid_high == 0)
3707                 return False;
3708
3709         if (low)
3710                 *low = idmap_uid_low;
3711
3712         if (high)
3713                 *high = idmap_uid_high;
3714
3715         return True;
3716 }
3717
3718 bool lp_idmap_gid(gid_t *low, gid_t *high)
3719 {
3720         if (idmap_gid_low == 0 || idmap_gid_high == 0)
3721                 return False;
3722
3723         if (low)
3724                 *low = idmap_gid_low;
3725
3726         if (high)
3727                 *high = idmap_gid_high;
3728
3729         return True;
3730 }
3731
3732 /* Do some simple checks on "idmap [ug]id" parameter values */
3733
3734 static bool handle_idmap_uid(int snum, const char *pszParmValue, char **ptr)
3735 {
3736         uint32 low, high;
3737
3738         if (sscanf(pszParmValue, "%u - %u", &low, &high) != 2 || high < low)
3739                 return False;
3740
3741         /* Parse OK */
3742
3743         string_set(ptr, pszParmValue);
3744
3745         idmap_uid_low = low;
3746         idmap_uid_high = high;
3747
3748         return True;
3749 }
3750
3751 static bool handle_idmap_gid(int snum, const char *pszParmValue, char **ptr)
3752 {
3753         uint32 low, high;
3754
3755         if (sscanf(pszParmValue, "%u - %u", &low, &high) != 2 || high < low)
3756                 return False;
3757
3758         /* Parse OK */
3759
3760         string_set(ptr, pszParmValue);
3761
3762         idmap_gid_low = low;
3763         idmap_gid_high = high;
3764
3765         return True;
3766 }
3767
3768 /***************************************************************************
3769  Handle the DEBUG level list.
3770 ***************************************************************************/
3771
3772 static bool handle_debug_list( int snum, const char *pszParmValueIn, char **ptr )
3773 {
3774         string_set(ptr, pszParmValueIn);
3775         return debug_parse_levels(pszParmValueIn);
3776 }
3777
3778 /***************************************************************************
3779  Handle ldap suffixes - default to ldapsuffix if sub-suffixes are not defined.
3780 ***************************************************************************/
3781
3782 static const char *append_ldap_suffix( const char *str )
3783 {
3784         const char *suffix_string;
3785
3786
3787         suffix_string = talloc_asprintf(talloc_tos(), "%s,%s", str,
3788                                         Globals.szLdapSuffix );
3789         if ( !suffix_string ) {
3790                 DEBUG(0,("append_ldap_suffix: talloc_asprintf() failed!\n"));
3791                 return "";
3792         }
3793
3794         return suffix_string;
3795 }
3796
3797 const char *lp_ldap_machine_suffix(void)
3798 {
3799         if (Globals.szLdapMachineSuffix[0])
3800                 return append_ldap_suffix(Globals.szLdapMachineSuffix);
3801
3802         return lp_string(Globals.szLdapSuffix);
3803 }
3804
3805 const char *lp_ldap_user_suffix(void)
3806 {
3807         if (Globals.szLdapUserSuffix[0])
3808                 return append_ldap_suffix(Globals.szLdapUserSuffix);
3809
3810         return lp_string(Globals.szLdapSuffix);
3811 }
3812
3813 const char *lp_ldap_group_suffix(void)
3814 {
3815         if (Globals.szLdapGroupSuffix[0])
3816                 return append_ldap_suffix(Globals.szLdapGroupSuffix);
3817
3818         return lp_string(Globals.szLdapSuffix);
3819 }
3820
3821 const char *lp_ldap_idmap_suffix(void)
3822 {
3823         if (Globals.szLdapIdmapSuffix[0])
3824                 return append_ldap_suffix(Globals.szLdapIdmapSuffix);
3825
3826         return lp_string(Globals.szLdapSuffix);
3827 }
3828
3829 /****************************************************************************
3830  set the value for a P_ENUM
3831  ***************************************************************************/
3832
3833 static void lp_set_enum_parm( struct parm_struct *parm, const char *pszParmValue,
3834                               int *ptr )
3835 {
3836         int i;
3837
3838         for (i = 0; parm->enum_list[i].name; i++) {
3839                 if ( strequal(pszParmValue, parm->enum_list[i].name)) {
3840                         *ptr = parm->enum_list[i].value;
3841                         break;
3842                 }
3843         }
3844 }
3845
3846 /***************************************************************************
3847 ***************************************************************************/
3848
3849 static bool handle_printing(int snum, const char *pszParmValue, char **ptr)
3850 {
3851         static int parm_num = -1;
3852         service *s;
3853
3854         if ( parm_num == -1 )
3855                 parm_num = map_parameter( "printing" );
3856
3857         lp_set_enum_parm( &parm_table[parm_num], pszParmValue, (int*)ptr );
3858
3859         if ( snum < 0 )
3860                 s = &sDefault;
3861         else
3862                 s = ServicePtrs[snum];
3863
3864         init_printer_values( s );
3865
3866         return True;
3867 }
3868
3869
3870 /***************************************************************************
3871  Initialise a copymap.
3872 ***************************************************************************/
3873
3874 static void init_copymap(service * pservice)
3875 {
3876         int i;
3877         if (pservice->copymap) {
3878                 bitmap_free(pservice->copymap);
3879         }
3880         pservice->copymap = bitmap_allocate(NUMPARAMETERS);
3881         if (!pservice->copymap)
3882                 DEBUG(0,
3883                       ("Couldn't allocate copymap!! (size %d)\n",
3884                        (int)NUMPARAMETERS));
3885         else
3886                 for (i = 0; i < NUMPARAMETERS; i++)
3887                         bitmap_set(pservice->copymap, i);
3888 }
3889
3890 /***************************************************************************
3891  Return the local pointer to a parameter given the service number and the 
3892  pointer into the default structure.
3893 ***************************************************************************/
3894
3895 void *lp_local_ptr(int snum, void *ptr)
3896 {
3897         return (void *)(((char *)ServicePtrs[snum]) + PTR_DIFF(ptr, &sDefault));
3898 }
3899
3900 /***************************************************************************
3901  Process a parameter for a particular service number. If snum < 0
3902  then assume we are in the globals.
3903 ***************************************************************************/
3904
3905 bool lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue)
3906 {
3907         int parmnum, i, slen;
3908         void *parm_ptr = NULL;  /* where we are going to store the result */
3909         void *def_ptr = NULL;
3910         char *param_key = NULL;
3911         char *sep;
3912         param_opt_struct *paramo, *data;
3913         bool not_added;
3914
3915         parmnum = map_parameter(pszParmName);
3916
3917         if (parmnum < 0) {
3918                 if ((sep=strchr(pszParmName, ':')) != NULL) {
3919                         TALLOC_CTX *frame = talloc_stackframe();
3920
3921                         *sep = '\0';
3922                         param_key = talloc_asprintf(frame, "%s:", pszParmName);
3923                         if (!param_key) {
3924                                 TALLOC_FREE(frame);
3925                                 return false;
3926                         }
3927                         slen = strlen(param_key);
3928                         param_key = talloc_asprintf_append(param_key, sep+1);
3929                         if (!param_key) {
3930                                 TALLOC_FREE(frame);
3931                                 return false;
3932                         }
3933                         trim_char(param_key+slen, ' ', ' ');
3934                         not_added = True;
3935                         data = (snum < 0) ? Globals.param_opt :
3936                                 ServicePtrs[snum]->param_opt;
3937                         /* Traverse destination */
3938                         while (data) {
3939                                 /* If we already have same option, override it */
3940                                 if (strcmp(data->key, param_key) == 0) {
3941                                         string_free(&data->value);
3942                                         TALLOC_FREE(data->list);
3943                                         data->value = SMB_STRDUP(pszParmValue);
3944                                         not_added = False;
3945                                         break;
3946                                 }
3947                                 data = data->next;
3948                         }
3949                         if (not_added) {
3950                                 paramo = SMB_XMALLOC_P(param_opt_struct);
3951                                 paramo->key = SMB_STRDUP(param_key);
3952                                 paramo->value = SMB_STRDUP(pszParmValue);
3953                                 paramo->list = NULL;
3954                                 if (snum < 0) {
3955                                         DLIST_ADD(Globals.param_opt, paramo);
3956                                 } else {
3957                                         DLIST_ADD(ServicePtrs[snum]->param_opt, paramo);
3958                                 }
3959                         }
3960
3961                         *sep = ':';
3962                         TALLOC_FREE(frame);
3963                         return (True);
3964                 }
3965                 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n", pszParmName));
3966                 return (True);
3967         }
3968
3969         if (parm_table[parmnum].flags & FLAG_DEPRECATED) {
3970                 DEBUG(1, ("WARNING: The \"%s\" option is deprecated\n",
3971                           pszParmName));
3972         }
3973
3974         def_ptr = parm_table[parmnum].ptr;
3975
3976         /* we might point at a service, the default service or a global */
3977         if (snum < 0) {
3978                 parm_ptr = def_ptr;
3979         } else {
3980                 if (parm_table[parmnum].p_class == P_GLOBAL) {
3981                         DEBUG(0,
3982                               ("Global parameter %s found in service section!\n",
3983                                pszParmName));
3984                         return (True);
3985                 }
3986                 parm_ptr =
3987                         ((char *)ServicePtrs[snum]) + PTR_DIFF(def_ptr,
3988                                                             &sDefault);
3989         }
3990
3991         if (snum >= 0) {
3992                 if (!ServicePtrs[snum]->copymap)
3993                         init_copymap(ServicePtrs[snum]);
3994
3995                 /* this handles the aliases - set the copymap for other entries with
3996                    the same data pointer */
3997                 for (i = 0; parm_table[i].label; i++)
3998                         if (parm_table[i].ptr == parm_table[parmnum].ptr)
3999                                 bitmap_clear(ServicePtrs[snum]->copymap, i);
4000         }
4001
4002         /* if it is a special case then go ahead */
4003         if (parm_table[parmnum].special) {
4004                 parm_table[parmnum].special(snum, pszParmValue, (char **)parm_ptr);
4005                 return (True);
4006         }
4007
4008         /* now switch on the type of variable it is */
4009         switch (parm_table[parmnum].type)
4010         {
4011                 case P_BOOL:
4012                         *(bool *)parm_ptr = lp_bool(pszParmValue);
4013                         break;
4014
4015                 case P_BOOLREV:
4016                         *(bool *)parm_ptr = !lp_bool(pszParmValue);
4017                         break;
4018
4019                 case P_INTEGER:
4020                         *(int *)parm_ptr = lp_int(pszParmValue);
4021                         break;
4022
4023                 case P_CHAR:
4024                         *(char *)parm_ptr = *pszParmValue;
4025                         break;
4026
4027                 case P_OCTAL:
4028                         i = sscanf(pszParmValue, "%o", (int *)parm_ptr);
4029                         if ( i != 1 ) {
4030                             DEBUG ( 0, ("Invalid octal number %s\n", pszParmName ));
4031                         }
4032                         break;
4033
4034                 case P_LIST:
4035                         TALLOC_FREE(*((char ***)parm_ptr));
4036                         *(char ***)parm_ptr = str_list_make(
4037                                 NULL, pszParmValue, NULL);
4038                         break;
4039
4040                 case P_STRING:
4041                         string_set((char **)parm_ptr, pszParmValue);
4042                         break;
4043
4044                 case P_USTRING:
4045                         string_set((char **)parm_ptr, pszParmValue);
4046                         strupper_m(*(char **)parm_ptr);
4047                         break;
4048
4049                 case P_ENUM:
4050                         lp_set_enum_parm( &parm_table[parmnum], pszParmValue, (int*)parm_ptr );
4051                         break;
4052                 case P_SEP:
4053                         break;
4054         }
4055
4056         return (True);
4057 }
4058
4059 /***************************************************************************
4060  Process a parameter.
4061 ***************************************************************************/
4062
4063 static bool do_parameter(const char *pszParmName, const char *pszParmValue)
4064 {
4065         if (!bInGlobalSection && bGlobalOnly)
4066                 return (True);
4067
4068         DEBUGADD(4, ("doing parameter %s = %s\n", pszParmName, pszParmValue));
4069
4070         return (lp_do_parameter(bInGlobalSection ? -2 : iServiceIndex,
4071                                 pszParmName, pszParmValue));
4072 }
4073
4074 /***************************************************************************
4075  Print a parameter of the specified type.
4076 ***************************************************************************/
4077
4078 static void print_parameter(struct parm_struct *p, void *ptr, FILE * f)
4079 {
4080         int i;
4081         switch (p->type)
4082         {
4083                 case P_ENUM:
4084                         for (i = 0; p->enum_list[i].name; i++) {
4085                                 if (*(int *)ptr == p->enum_list[i].value) {
4086                                         fprintf(f, "%s",
4087                                                 p->enum_list[i].name);
4088                                         break;
4089                                 }
4090                         }
4091                         break;
4092
4093                 case P_BOOL:
4094                         fprintf(f, "%s", BOOLSTR(*(bool *)ptr));
4095                         break;
4096
4097                 case P_BOOLREV:
4098                         fprintf(f, "%s", BOOLSTR(!*(bool *)ptr));
4099                         break;
4100
4101                 case P_INTEGER:
4102                         fprintf(f, "%d", *(int *)ptr);
4103                         break;
4104
4105                 case P_CHAR:
4106                         fprintf(f, "%c", *(char *)ptr);
4107                         break;
4108
4109                 case P_OCTAL: {
4110                         char *o = octal_string(*(int *)ptr);
4111                         fprintf(f, "%s", o);
4112                         TALLOC_FREE(o);
4113                         break;
4114                 }
4115
4116                 case P_LIST:
4117                         if ((char ***)ptr && *(char ***)ptr) {
4118                                 char **list = *(char ***)ptr;
4119                                 for (; *list; list++) {
4120                                         /* surround strings with whitespace in double quotes */
4121                                         if ( strchr_m( *list, ' ' ) )
4122                                                 fprintf(f, "\"%s\"%s", *list, ((*(list+1))?", ":""));
4123                                         else
4124                                                 fprintf(f, "%s%s", *list, ((*(list+1))?", ":""));
4125                                 }
4126                         }
4127                         break;
4128
4129                 case P_STRING:
4130                 case P_USTRING:
4131                         if (*(char **)ptr) {
4132                                 fprintf(f, "%s", *(char **)ptr);
4133                         }
4134                         break;
4135                 case P_SEP:
4136                         break;
4137         }
4138 }
4139
4140 /***************************************************************************
4141  Check if two parameters are equal.
4142 ***************************************************************************/
4143
4144 static bool equal_parameter(parm_type type, void *ptr1, void *ptr2)
4145 {
4146         switch (type) {
4147                 case P_BOOL:
4148                 case P_BOOLREV:
4149                         return (*((bool *)ptr1) == *((bool *)ptr2));
4150
4151                 case P_INTEGER:
4152                 case P_ENUM:
4153                 case P_OCTAL:
4154                         return (*((int *)ptr1) == *((int *)ptr2));
4155
4156                 case P_CHAR:
4157                         return (*((char *)ptr1) == *((char *)ptr2));
4158
4159                 case P_LIST:
4160                         return str_list_compare(*(char ***)ptr1, *(char ***)ptr2);
4161
4162                 case P_STRING:
4163                 case P_USTRING:
4164                 {
4165                         char *p1 = *(char **)ptr1, *p2 = *(char **)ptr2;
4166                         if (p1 && !*p1)
4167                                 p1 = NULL;
4168                         if (p2 && !*p2)
4169                                 p2 = NULL;
4170                         return (p1 == p2 || strequal(p1, p2));
4171                 }
4172                 case P_SEP:
4173                         break;
4174         }
4175         return (False);
4176 }
4177
4178 /***************************************************************************
4179  Initialize any local varients in the sDefault table.
4180 ***************************************************************************/
4181
4182 void init_locals(void)
4183 {
4184         /* None as yet. */
4185 }
4186
4187 /***************************************************************************
4188  Process a new section (service). At this stage all sections are services.
4189  Later we'll have special sections that permit server parameters to be set.
4190  Returns True on success, False on failure. 
4191 ***************************************************************************/
4192
4193 static bool do_section(const char *pszSectionName)
4194 {
4195         bool bRetval;
4196         bool isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
4197                          (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
4198         bRetval = False;
4199
4200         /* if we were in a global section then do the local inits */
4201         if (bInGlobalSection && !isglobal)
4202                 init_locals();
4203
4204         /* if we've just struck a global section, note the fact. */
4205         bInGlobalSection = isglobal;
4206
4207         /* check for multiple global sections */
4208         if (bInGlobalSection) {
4209                 DEBUG(3, ("Processing section \"[%s]\"\n", pszSectionName));
4210                 return (True);
4211         }
4212
4213         if (!bInGlobalSection && bGlobalOnly)
4214                 return (True);
4215
4216         /* if we have a current service, tidy it up before moving on */
4217         bRetval = True;
4218
4219         if (iServiceIndex >= 0)
4220                 bRetval = service_ok(iServiceIndex);
4221
4222         /* if all is still well, move to the next record in the services array */
4223         if (bRetval) {
4224                 /* We put this here to avoid an odd message order if messages are */
4225                 /* issued by the post-processing of a previous section. */
4226                 DEBUG(2, ("Processing section \"[%s]\"\n", pszSectionName));
4227
4228                 if ((iServiceIndex = add_a_service(&sDefault, pszSectionName))
4229                     < 0) {
4230                         DEBUG(0, ("Failed to add a new service\n"));
4231                         return (False);
4232                 }
4233         }
4234
4235         return (bRetval);
4236 }
4237
4238
4239 /***************************************************************************
4240  Determine if a partcular base parameter is currentl set to the default value.
4241 ***************************************************************************/
4242
4243 static bool is_default(int i)
4244 {
4245         if (!defaults_saved)
4246                 return False;
4247         switch (parm_table[i].type) {
4248                 case P_LIST:
4249                         return str_list_compare (parm_table[i].def.lvalue, 
4250                                                 *(char ***)parm_table[i].ptr);
4251                 case P_STRING:
4252                 case P_USTRING:
4253                         return strequal(parm_table[i].def.svalue,
4254                                         *(char **)parm_table[i].ptr);
4255                 case P_BOOL:
4256                 case P_BOOLREV:
4257                         return parm_table[i].def.bvalue ==
4258                                 *(bool *)parm_table[i].ptr;
4259                 case P_CHAR:
4260                         return parm_table[i].def.cvalue ==
4261                                 *(char *)parm_table[i].ptr;
4262                 case P_INTEGER:
4263                 case P_OCTAL:
4264                 case P_ENUM:
4265                         return parm_table[i].def.ivalue ==
4266                                 *(int *)parm_table[i].ptr;
4267                 case P_SEP:
4268                         break;
4269         }
4270         return False;
4271 }
4272
4273 /***************************************************************************
4274 Display the contents of the global structure.
4275 ***************************************************************************/
4276
4277 static void dump_globals(FILE *f)
4278 {
4279         int i;
4280         param_opt_struct *data;
4281         
4282         fprintf(f, "[global]\n");
4283
4284         for (i = 0; parm_table[i].label; i++)
4285                 if (parm_table[i].p_class == P_GLOBAL &&
4286                     parm_table[i].ptr &&
4287                     (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) {
4288                         if (defaults_saved && is_default(i))
4289                                 continue;
4290                         fprintf(f, "\t%s = ", parm_table[i].label);
4291                         print_parameter(&parm_table[i], parm_table[i].ptr, f);
4292                         fprintf(f, "\n");
4293         }
4294         if (Globals.param_opt != NULL) {
4295                 data = Globals.param_opt;
4296                 while(data) {
4297                         fprintf(f, "\t%s = %s\n", data->key, data->value);
4298                         data = data->next;
4299                 }
4300         }
4301
4302 }
4303
4304 /***************************************************************************
4305  Return True if a local parameter is currently set to the global default.
4306 ***************************************************************************/
4307
4308 bool lp_is_default(int snum, struct parm_struct *parm)
4309 {
4310         int pdiff = PTR_DIFF(parm->ptr, &sDefault);
4311
4312         return equal_parameter(parm->type,
4313                                ((char *)ServicePtrs[snum]) + pdiff,
4314                                ((char *)&sDefault) + pdiff);
4315 }
4316
4317 /***************************************************************************
4318  Display the contents of a single services record.
4319 ***************************************************************************/
4320
4321 static void dump_a_service(service * pService, FILE * f)
4322 {
4323         int i;
4324         param_opt_struct *data;
4325         
4326         if (pService != &sDefault)
4327                 fprintf(f, "[%s]\n", pService->szService);
4328
4329         for (i = 0; parm_table[i].label; i++) {
4330
4331                 if (parm_table[i].p_class == P_LOCAL &&
4332                     parm_table[i].ptr &&
4333                     (*parm_table[i].label != '-') &&
4334                     (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) 
4335                 {
4336                 
4337                         int pdiff = PTR_DIFF(parm_table[i].ptr, &sDefault);
4338
4339                         if (pService == &sDefault) {
4340                                 if (defaults_saved && is_default(i))
4341                                         continue;
4342                         } else {
4343                                 if (equal_parameter(parm_table[i].type,
4344                                                     ((char *)pService) +
4345                                                     pdiff,
4346                                                     ((char *)&sDefault) +
4347                                                     pdiff))
4348                                         continue;
4349                         }
4350
4351                         fprintf(f, "\t%s = ", parm_table[i].label);
4352                         print_parameter(&parm_table[i],
4353                                         ((char *)pService) + pdiff, f);
4354                         fprintf(f, "\n");
4355                 }
4356         }
4357
4358                 if (pService->param_opt != NULL) {
4359                         data = pService->param_opt;
4360                         while(data) {
4361                                 fprintf(f, "\t%s = %s\n", data->key, data->value);
4362                                 data = data->next;
4363                         }
4364                 }
4365 }
4366
4367 /***************************************************************************
4368  Display the contents of a parameter of a single services record.
4369 ***************************************************************************/
4370
4371 bool dump_a_parameter(int snum, char *parm_name, FILE * f, bool isGlobal)
4372 {
4373         int i;
4374         bool result = False;
4375         parm_class p_class;
4376         unsigned flag = 0;
4377         fstring local_parm_name;
4378         char *parm_opt;
4379         const char *parm_opt_value;
4380
4381         /* check for parametrical option */
4382         fstrcpy( local_parm_name, parm_name);
4383         parm_opt = strchr( local_parm_name, ':');
4384
4385         if (parm_opt) {
4386                 *parm_opt = '\0';
4387                 parm_opt++;
4388                 if (strlen(parm_opt)) {
4389                         parm_opt_value = lp_parm_const_string( snum,
4390                                 local_parm_name, parm_opt, NULL);
4391                         if (parm_opt_value) {
4392                                 printf( "%s\n", parm_opt_value);
4393                                 result = True;
4394                         }
4395                 }
4396                 return result;
4397         }
4398
4399         /* check for a key and print the value */
4400         if (isGlobal) {
4401                 p_class = P_GLOBAL;
4402                 flag = FLAG_GLOBAL;
4403         } else
4404                 p_class = P_LOCAL;
4405
4406         for (i = 0; parm_table[i].label; i++) {
4407                 if (strwicmp(parm_table[i].label, parm_name) == 0 &&
4408                     (parm_table[i].p_class == p_class || parm_table[i].flags & flag) &&
4409                     parm_table[i].ptr &&
4410                     (*parm_table[i].label != '-') &&
4411                     (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) 
4412                 {
4413                         void *ptr;
4414
4415                         if (isGlobal) {
4416                                 ptr = parm_table[i].ptr;
4417                         } else {
4418                                 service * pService = ServicePtrs[snum];
4419                                 ptr = ((char *)pService) +
4420                                         PTR_DIFF(parm_table[i].ptr, &sDefault);
4421                         }
4422
4423                         print_parameter(&parm_table[i],
4424                                         ptr, f);
4425                         fprintf(f, "\n");
4426                         result = True;
4427                         break;
4428                 }
4429         }
4430
4431         return result;
4432 }
4433
4434 /***************************************************************************
4435  Return info about the requested parameter (given as a string).
4436  Return NULL when the string is not a valid parameter name.
4437 ***************************************************************************/
4438
4439 struct parm_struct *lp_get_parameter(const char *param_name)
4440 {
4441         int num = map_parameter(param_name);
4442
4443         if (num < 0) {
4444                 return NULL;
4445         }
4446
4447         return &parm_table[num];
4448 }
4449
4450 /***************************************************************************
4451  Return info about the next parameter in a service.
4452  snum==GLOBAL_SECTION_SNUM gives the globals.
4453  Return NULL when out of parameters.
4454 ***************************************************************************/
4455
4456 struct parm_struct *lp_next_parameter(int snum, int *i, int allparameters)
4457 {
4458         if (snum < 0) {
4459                 /* do the globals */
4460                 for (; parm_table[*i].label; (*i)++) {
4461                         if (parm_table[*i].p_class == P_SEPARATOR)
4462                                 return &parm_table[(*i)++];
4463
4464                         if (!parm_table[*i].ptr
4465                             || (*parm_table[*i].label == '-'))
4466                                 continue;
4467
4468                         if ((*i) > 0
4469                             && (parm_table[*i].ptr ==
4470                                 parm_table[(*i) - 1].ptr))
4471                                 continue;
4472                         
4473                         if (is_default(*i) && !allparameters)
4474                                 continue;
4475
4476                         return &parm_table[(*i)++];
4477                 }
4478         } else {
4479                 service *pService = ServicePtrs[snum];
4480
4481                 for (; parm_table[*i].label; (*i)++) {
4482                         if (parm_table[*i].p_class == P_SEPARATOR)
4483                                 return &parm_table[(*i)++];
4484
4485                         if (parm_table[*i].p_class == P_LOCAL &&
4486                             parm_table[*i].ptr &&
4487                             (*parm_table[*i].label != '-') &&
4488                             ((*i) == 0 ||
4489                              (parm_table[*i].ptr !=
4490                               parm_table[(*i) - 1].ptr)))
4491                         {
4492                                 int pdiff =
4493                                         PTR_DIFF(parm_table[*i].ptr,
4494                                                  &sDefault);
4495
4496                                 if (allparameters ||
4497                                     !equal_parameter(parm_table[*i].type,
4498                                                      ((char *)pService) +
4499                                                      pdiff,
4500                                                      ((char *)&sDefault) +
4501                                                      pdiff))
4502                                 {
4503                                         return &parm_table[(*i)++];
4504                                 }
4505                         }
4506                 }
4507         }
4508
4509         return NULL;
4510 }
4511
4512
4513 #if 0
4514 /***************************************************************************
4515  Display the contents of a single copy structure.
4516 ***************************************************************************/
4517 static void dump_copy_map(bool *pcopymap)
4518 {
4519         int i;
4520         if (!pcopymap)
4521                 return;
4522
4523         printf("\n\tNon-Copied parameters:\n");
4524
4525         for (i = 0; parm_table[i].label; i++)
4526                 if (parm_table[i].p_class == P_LOCAL &&
4527                     parm_table[i].ptr && !pcopymap[i] &&
4528                     (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr)))
4529                 {
4530                         printf("\t\t%s\n", parm_table[i].label);
4531                 }
4532 }
4533 #endif
4534
4535 /***************************************************************************
4536  Return TRUE if the passed service number is within range.
4537 ***************************************************************************/
4538
4539 bool lp_snum_ok(int iService)
4540 {
4541         return (LP_SNUM_OK(iService) && ServicePtrs[iService]->bAvailable);
4542 }
4543
4544 /***************************************************************************
4545  Auto-load some home services.
4546 ***************************************************************************/
4547
4548 static void lp_add_auto_services(char *str)
4549 {
4550         char *s;
4551         char *p;
4552         int homes;
4553         char *saveptr;
4554
4555         if (!str)
4556                 return;
4557
4558         s = SMB_STRDUP(str);
4559         if (!s)
4560                 return;
4561
4562         homes = lp_servicenumber(HOMES_NAME);
4563
4564         for (p = strtok_r(s, LIST_SEP, &saveptr); p;
4565              p = strtok_r(NULL, LIST_SEP, &saveptr)) {
4566                 char *home;
4567
4568                 if (lp_servicenumber(p) >= 0)
4569                         continue;
4570
4571                 home = get_user_home_dir(talloc_tos(), p);
4572
4573                 if (home && homes >= 0)
4574                         lp_add_home(p, homes, p, home);
4575
4576                 TALLOC_FREE(home);
4577         }
4578         SAFE_FREE(s);
4579 }
4580
4581 /***************************************************************************
4582  Auto-load one printer.
4583 ***************************************************************************/
4584
4585 void lp_add_one_printer(char *name, char *comment)
4586 {
4587         int printers = lp_servicenumber(PRINTERS_NAME);
4588         int i;
4589
4590         if (lp_servicenumber(name) < 0) {
4591                 lp_add_printer(name, printers);
4592                 if ((i = lp_servicenumber(name)) >= 0) {
4593                         string_set(&ServicePtrs[i]->comment, comment);
4594                         ServicePtrs[i]->autoloaded = True;
4595                 }
4596         }
4597 }
4598
4599 /***************************************************************************
4600  Have we loaded a services file yet?
4601 ***************************************************************************/
4602
4603 bool lp_loaded(void)
4604 {
4605         return (bLoaded);
4606 }
4607
4608 /***************************************************************************
4609  Unload unused services.
4610 ***************************************************************************/
4611
4612 void lp_killunused(bool (*snumused) (int))
4613 {
4614         int i;
4615         for (i = 0; i < iNumServices; i++) {
4616                 if (!VALID(i))
4617                         continue;
4618
4619                 /* don't kill autoloaded or usershare services */
4620                 if ( ServicePtrs[i]->autoloaded ||
4621                                 ServicePtrs[i]->usershare == USERSHARE_VALID) {
4622                         continue;
4623                 }
4624
4625                 if (!snumused || !snumused(i)) {
4626                         free_service_byindex(i);
4627                 }
4628         }
4629 }
4630
4631 /***************************************************************************
4632  Unload a service.
4633 ***************************************************************************/
4634
4635 void lp_killservice(int iServiceIn)
4636 {
4637         if (VALID(iServiceIn)) {
4638                 free_service_byindex(iServiceIn);
4639         }
4640 }
4641
4642 /***************************************************************************
4643  Save the curent values of all global and sDefault parameters into the 
4644  defaults union. This allows swat and testparm to show only the
4645  changed (ie. non-default) parameters.
4646 ***************************************************************************/
4647
4648 static void lp_save_defaults(void)
4649 {
4650         int i;
4651         for (i = 0; parm_table[i].label; i++) {
4652                 if (i > 0 && parm_table[i].ptr == parm_table[i - 1].ptr)
4653                         continue;
4654                 switch (parm_table[i].type) {
4655                         case P_LIST:
4656                                 str_list_copy(
4657                                         NULL, &(parm_table[i].def.lvalue),
4658                                         *(const char ***)parm_table[i].ptr);
4659                                 break;
4660                         case P_STRING:
4661                         case P_USTRING:
4662                                 if (parm_table[i].ptr) {
4663                                         parm_table[i].def.svalue = SMB_STRDUP(*(char **)parm_table[i].ptr);
4664                                 } else {
4665                                         parm_table[i].def.svalue = NULL;
4666                                 }
4667                                 break;
4668                         case P_BOOL:
4669                         case P_BOOLREV:
4670                                 parm_table[i].def.bvalue =
4671                                         *(bool *)parm_table[i].ptr;
4672                                 break;
4673                         case P_CHAR:
4674                                 parm_table[i].def.cvalue =
4675                                         *(char *)parm_table[i].ptr;
4676                                 break;
4677                         case P_INTEGER:
4678                         case P_OCTAL:
4679                         case P_ENUM:
4680                                 parm_table[i].def.ivalue =
4681                                         *(int *)parm_table[i].ptr;
4682                                 break;
4683                         case P_SEP:
4684                                 break;
4685                 }
4686         }
4687         defaults_saved = True;
4688 }
4689
4690 /*******************************************************************
4691  Set the server type we will announce as via nmbd.
4692 ********************************************************************/
4693
4694 static const struct srv_role_tab {
4695         uint32 role;
4696         const char *role_str;
4697 } srv_role_tab [] = {
4698         { ROLE_STANDALONE, "ROLE_STANDALONE" },
4699         { ROLE_DOMAIN_MEMBER, "ROLE_DOMAIN_MEMBER" },
4700         { ROLE_DOMAIN_BDC, "ROLE_DOMAIN_BDC" },
4701         { ROLE_DOMAIN_PDC, "ROLE_DOMAIN_PDC" },
4702         { 0, NULL }
4703 };
4704
4705 const char* server_role_str(uint32 role)
4706 {
4707         int i = 0;
4708         for (i=0; srv_role_tab[i].role_str; i++) {
4709                 if (role == srv_role_tab[i].role) {
4710                         return srv_role_tab[i].role_str;
4711                 }
4712         }
4713         return NULL;
4714 }
4715
4716 static void set_server_role(void)
4717 {
4718         server_role = ROLE_STANDALONE;
4719
4720         switch (lp_security()) {
4721                 case SEC_SHARE:
4722                         if (lp_domain_logons())
4723                                 DEBUG(0, ("Server's Role (logon server) conflicts with share-level security\n"));
4724                         break;
4725                 case SEC_SERVER:
4726                         if (lp_domain_logons())
4727                                 DEBUG(0, ("Server's Role (logon server) conflicts with server-level security\n"));
4728                         /* this used to be considered ROLE_DOMAIN_MEMBER but that's just wrong */
4729                         server_role = ROLE_STANDALONE;
4730                         break;
4731                 case SEC_DOMAIN:
4732                         if (lp_domain_logons()) {
4733                                 DEBUG(1, ("Server's Role (logon server) NOT ADVISED with domain-level security\n"));
4734                                 server_role = ROLE_DOMAIN_BDC;
4735                                 break;
4736                         }
4737                         server_role = ROLE_DOMAIN_MEMBER;
4738                         break;
4739                 case SEC_ADS:
4740                         if (lp_domain_logons()) {
4741                                 server_role = ROLE_DOMAIN_PDC;
4742                                 break;
4743                         }
4744                         server_role = ROLE_DOMAIN_MEMBER;
4745                         break;
4746                 case SEC_USER:
4747                         if (lp_domain_logons()) {
4748
4749                                 if (Globals.iDomainMaster) /* auto or yes */ 
4750                                         server_role = ROLE_DOMAIN_PDC;
4751                                 else
4752                                         server_role = ROLE_DOMAIN_BDC;
4753                         }
4754                         break;
4755                 default:
4756                         DEBUG(0, ("Server's Role undefined due to unknown security mode\n"));
4757                         break;
4758         }
4759
4760         DEBUG(10, ("set_server_role: role = %s\n", server_role_str(server_role)));
4761 }
4762
4763 /***********************************************************
4764  If we should send plaintext/LANMAN passwords in the clinet
4765 ************************************************************/
4766
4767 static void set_allowed_client_auth(void)
4768 {
4769         if (Globals.bClientNTLMv2Auth) {
4770                 Globals.bClientLanManAuth = False;
4771         }
4772         if (!Globals.bClientLanManAuth) {
4773                 Globals.bClientPlaintextAuth = False;
4774         }
4775 }
4776
4777 /***************************************************************************
4778  JRA.
4779  The following code allows smbd to read a user defined share file.
4780  Yes, this is my intent. Yes, I'm comfortable with that...
4781
4782  THE FOLLOWING IS SECURITY CRITICAL CODE.
4783
4784  It washes your clothes, it cleans your house, it guards you while you sleep...
4785  Do not f%^k with it....
4786 ***************************************************************************/
4787
4788 #define MAX_USERSHARE_FILE_SIZE (10*1024)
4789
4790 /***************************************************************************
4791  Check allowed stat state of a usershare file.
4792  Ensure we print out who is dicking with us so the admin can
4793  get their sorry ass fired.
4794 ***************************************************************************/
4795
4796 static bool check_usershare_stat(const char *fname, SMB_STRUCT_STAT *psbuf)
4797 {
4798         if (!S_ISREG(psbuf->st_mode)) {
4799                 DEBUG(0,("check_usershare_stat: file %s owned by uid %u is "
4800                         "not a regular file\n",
4801                         fname, (unsigned int)psbuf->st_uid ));
4802                 return False;
4803         }
4804
4805         /* Ensure this doesn't have the other write bit set. */
4806         if (psbuf->st_mode & S_IWOTH) {
4807                 DEBUG(0,("check_usershare_stat: file %s owned by uid %u allows "
4808                         "public write. Refusing to allow as a usershare file.\n",
4809                         fname, (unsigned int)psbuf->st_uid ));
4810                 return False;
4811         }
4812
4813         /* Should be 10k or less. */
4814         if (psbuf->st_size > MAX_USERSHARE_FILE_SIZE) {
4815                 DEBUG(0,("check_usershare_stat: file %s owned by uid %u is "
4816                         "too large (%u) to be a user share file.\n",
4817                         fname, (unsigned int)psbuf->st_uid,
4818                         (unsigned int)psbuf->st_size ));
4819                 return False;
4820         }
4821
4822         return True;
4823 }
4824
4825 /***************************************************************************
4826  Parse the contents of a usershare file.
4827 ***************************************************************************/
4828
4829 enum usershare_err parse_usershare_file(TALLOC_CTX *ctx,
4830                         SMB_STRUCT_STAT *psbuf,
4831                         const char *servicename,
4832                         int snum,
4833                         char **lines,
4834                         int numlines,
4835                         char **pp_sharepath,
4836                         char **pp_comment,
4837                         SEC_DESC **ppsd,
4838                         bool *pallow_guest)
4839 {
4840         const char **prefixallowlist = lp_usershare_prefix_allow_list();
4841         const char **prefixdenylist = lp_usershare_prefix_deny_list();
4842         int us_vers;
4843         SMB_STRUCT_DIR *dp;
4844         SMB_STRUCT_STAT sbuf;
4845         char *sharepath = NULL;
4846         char *comment = NULL;
4847
4848         *pp_sharepath = NULL;
4849         *pp_comment = NULL;
4850
4851         *pallow_guest = False;
4852
4853         if (numlines < 4) {
4854                 return USERSHARE_MALFORMED_FILE;
4855         }
4856
4857         if (strcmp(lines[0], "#VERSION 1") == 0) {
4858                 us_vers = 1;
4859         } else if (strcmp(lines[0], "#VERSION 2") == 0) {
4860                 us_vers = 2;
4861                 if (numlines < 5) {
4862                         return USERSHARE_MALFORMED_FILE;
4863                 }
4864         } else {
4865                 return USERSHARE_BAD_VERSION;
4866         }
4867
4868         if (strncmp(lines[1], "path=", 5) != 0) {
4869                 return USERSHARE_MALFORMED_PATH;
4870         }
4871
4872         sharepath = talloc_strdup(ctx, &lines[1][5]);
4873         if (!sharepath) {
4874                 return USERSHARE_POSIX_ERR;
4875         }
4876         trim_string(sharepath, " ", " ");
4877
4878         if (strncmp(lines[2], "comment=", 8) != 0) {
4879                 return USERSHARE_MALFORMED_COMMENT_DEF;
4880         }
4881
4882         comment = talloc_strdup(ctx, &lines[2][8]);
4883         if (!comment) {
4884                 return USERSHARE_POSIX_ERR;
4885         }
4886         trim_string(comment, " ", " ");
4887         trim_char(comment, '"', '"');
4888
4889         if (strncmp(lines[3], "usershare_acl=", 14) != 0) {
4890                 return USERSHARE_MALFORMED_ACL_DEF;
4891         }
4892
4893         if (!parse_usershare_acl(ctx, &lines[3][14], ppsd)) {
4894                 return USERSHARE_ACL_ERR;
4895         }
4896
4897         if (us_vers == 2) {
4898                 if (strncmp(lines[4], "guest_ok=", 9) != 0) {
4899                         return USERSHARE_MALFORMED_ACL_DEF;
4900                 }
4901                 if (lines[4][9] == 'y') {
4902                         *pallow_guest = True;
4903                 }
4904         }
4905
4906         if (snum != -1 && (strcmp(sharepath, ServicePtrs[snum]->szPath) == 0)) {
4907                 /* Path didn't change, no checks needed. */
4908                 *pp_sharepath = sharepath;
4909                 *pp_comment = comment;
4910                 return USERSHARE_OK;
4911         }
4912
4913         /* The path *must* be absolute. */
4914         if (sharepath[0] != '/') {
4915                 DEBUG(2,("parse_usershare_file: share %s: path %s is not an absolute path.\n",
4916                         servicename, sharepath));
4917                 return USERSHARE_PATH_NOT_ABSOLUTE;
4918         }
4919
4920         /* If there is a usershare prefix deny list ensure one of these paths
4921            doesn't match the start of the user given path. */
4922         if (prefixdenylist) {
4923                 int i;
4924                 for ( i=0; prefixdenylist[i]; i++ ) {
4925                         DEBUG(10,("parse_usershare_file: share %s : checking prefixdenylist[%d]='%s' against %s\n",
4926                                 servicename, i, prefixdenylist[i], sharepath ));
4927                         if (memcmp( sharepath, prefixdenylist[i], strlen(prefixdenylist[i])) == 0) {
4928                                 DEBUG(2,("parse_usershare_file: share %s path %s starts with one of the "
4929                                         "usershare prefix deny list entries.\n",
4930                                         servicename, sharepath));
4931                                 return USERSHARE_PATH_IS_DENIED;
4932                         }
4933                 }
4934         }
4935
4936         /* If there is a usershare prefix allow list ensure one of these paths
4937            does match the start of the user given path. */
4938
4939         if (prefixallowlist) {
4940                 int i;
4941                 for ( i=0; prefixallowlist[i]; i++ ) {
4942                         DEBUG(10,("parse_usershare_file: share %s checking prefixallowlist[%d]='%s' against %s\n",
4943                                 servicename, i, prefixallowlist[i], sharepath ));
4944                         if (memcmp( sharepath, prefixallowlist[i], strlen(prefixallowlist[i])) == 0) {
4945                                 break;
4946                         }
4947                 }
4948                 if (prefixallowlist[i] == NULL) {
4949                         DEBUG(2,("parse_usershare_file: share %s path %s doesn't start with one of the "
4950                                 "usershare prefix allow list entries.\n",
4951                                 servicename, sharepath));
4952                         return USERSHARE_PATH_NOT_ALLOWED;
4953                 }
4954         }
4955
4956         /* Ensure this is pointing to a directory. */
4957         dp = sys_opendir(sharepath);
4958
4959         if (!dp) {
4960                 DEBUG(2,("parse_usershare_file: share %s path %s is not a directory.\n",
4961                         servicename, sharepath));
4962                 return USERSHARE_PATH_NOT_DIRECTORY;
4963         }
4964
4965         /* Ensure the owner of the usershare file has permission to share
4966            this directory. */
4967
4968         if (sys_stat(sharepath, &sbuf) == -1) {
4969                 DEBUG(2,("parse_usershare_file: share %s : stat failed on path %s. %s\n",
4970                         servicename, sharepath, strerror(errno) ));
4971                 sys_closedir(dp);
4972                 return USERSHARE_POSIX_ERR;
4973         }
4974
4975         sys_closedir(dp);
4976
4977         if (!S_ISDIR(sbuf.st_mode)) {
4978                 DEBUG(2,("parse_usershare_file: share %s path %s is not a directory.\n",
4979                         servicename, sharepath ));
4980                 return USERSHARE_PATH_NOT_DIRECTORY;
4981         }
4982
4983         /* Check if sharing is restricted to owner-only. */
4984         /* psbuf is the stat of the usershare definition file,
4985            sbuf is the stat of the target directory to be shared. */
4986
4987         if (lp_usershare_owner_only()) {
4988                 /* root can share anything. */
4989                 if ((psbuf->st_uid != 0) && (sbuf.st_uid != psbuf->st_uid)) {
4990                         return USERSHARE_PATH_NOT_ALLOWED;
4991                 }
4992         }
4993
4994         *pp_sharepath = sharepath;
4995         *pp_comment = comment;
4996         return USERSHARE_OK;
4997 }
4998
4999 /***************************************************************************
5000  Deal with a usershare file.
5001  Returns:
5002         >= 0 - snum
5003         -1 - Bad name, invalid contents.
5004            - service name already existed and not a usershare, problem
5005             with permissions to share directory etc.
5006 ***************************************************************************/
5007
5008 static int process_usershare_file(const char *dir_name, const char *file_name, int snum_template)
5009 {
5010         SMB_STRUCT_STAT sbuf;
5011         SMB_STRUCT_STAT lsbuf;
5012         char *fname = NULL;
5013         char *sharepath = NULL;
5014         char *comment = NULL;
5015         fstring service_name;
5016         char **lines = NULL;
5017         int numlines = 0;
5018         int fd = -1;
5019         int iService = -1;
5020         TALLOC_CTX *ctx = NULL;
5021         SEC_DESC *psd = NULL;
5022         bool guest_ok = False;
5023
5024         /* Ensure share name doesn't contain invalid characters. */
5025         if (!validate_net_name(file_name, INVALID_SHARENAME_CHARS, strlen(file_name))) {
5026                 DEBUG(0,("process_usershare_file: share name %s contains "
5027                         "invalid characters (any of %s)\n",
5028                         file_name, INVALID_SHARENAME_CHARS ));
5029                 return -1;
5030         }
5031
5032         fstrcpy(service_name, file_name);
5033
5034         if (asprintf(&fname, "%s/%s", dir_name, file_name) < 0) {
5035         }
5036
5037         /* Minimize the race condition by doing an lstat before we
5038            open and fstat. Ensure this isn't a symlink link. */
5039
5040         if (sys_lstat(fname, &lsbuf) != 0) {
5041                 DEBUG(0,("process_usershare_file: stat of %s failed. %s\n",
5042                         fname, strerror(errno) ));
5043                 SAFE_FREE(fname);
5044                 return -1;
5045         }
5046
5047         /* This must be a regular file, not a symlink, directory or
5048            other strange filetype. */
5049         if (!check_usershare_stat(fname, &lsbuf)) {
5050                 SAFE_FREE(fname);
5051                 return -1;
5052         }
5053
5054         {
5055                 char *canon_name = canonicalize_servicename(service_name);
5056                 TDB_DATA data = dbwrap_fetch_bystring(
5057                         ServiceHash, canon_name, canon_name);
5058
5059                 iService = -1;
5060
5061                 if ((data.dptr != NULL) && (data.dsize == sizeof(iService))) {
5062                         iService = *(int *)data.dptr;
5063                 }
5064                 TALLOC_FREE(canon_name);
5065         }
5066
5067         if (iService != -1 && ServicePtrs[iService]->usershare_last_mod == lsbuf.st_mtime) {
5068                 /* Nothing changed - Mark valid and return. */
5069                 DEBUG(10,("process_usershare_file: service %s not changed.\n",
5070                         service_name ));
5071                 ServicePtrs[iService]->usershare = USERSHARE_VALID;
5072                 SAFE_FREE(fname);
5073                 return iService;
5074         }
5075
5076         /* Try and open the file read only - no symlinks allowed. */
5077 #ifdef O_NOFOLLOW
5078         fd = sys_open(fname, O_RDONLY|O_NOFOLLOW, 0);
5079 #else
5080         fd = sys_open(fname, O_RDONLY, 0);
5081 #endif
5082
5083         if (fd == -1) {
5084                 DEBUG(0,("process_usershare_file: unable to open %s. %s\n",
5085                         fname, strerror(errno) ));
5086                 SAFE_FREE(fname);
5087                 return -1;
5088         }
5089
5090         /* Now fstat to be *SURE* it's a regular file. */
5091         if (sys_fstat(fd, &sbuf) != 0) {
5092                 close(fd);
5093                 DEBUG(0,("process_usershare_file: fstat of %s failed. %s\n",
5094                         fname, strerror(errno) ));
5095                 SAFE_FREE(fname);
5096                 return -1;
5097         }
5098
5099         /* Is it the same dev/inode as was lstated ? */
5100         if (lsbuf.st_dev != sbuf.st_dev || lsbuf.st_ino != sbuf.st_ino) {
5101                 close(fd);
5102                 DEBUG(0,("process_usershare_file: fstat of %s is a different file from lstat. "
5103                         "Symlink spoofing going on ?\n", fname ));
5104                 SAFE_FREE(fname);
5105                 return -1;
5106         }
5107
5108         /* This must be a regular file, not a symlink, directory or
5109            other strange filetype. */
5110         if (!check_usershare_stat(fname, &sbuf)) {
5111                 SAFE_FREE(fname);
5112                 return -1;
5113         }
5114
5115         lines = fd_lines_load(fd, &numlines, MAX_USERSHARE_FILE_SIZE);
5116
5117         close(fd);
5118         if (lines == NULL) {
5119                 DEBUG(0,("process_usershare_file: loading file %s owned by %u failed.\n",
5120                         fname, (unsigned int)sbuf.st_uid ));
5121                 SAFE_FREE(fname);
5122                 return -1;
5123         }
5124
5125         SAFE_FREE(fname);
5126
5127         /* Should we allow printers to be shared... ? */
5128         ctx = talloc_init("usershare_sd_xctx");
5129         if (!ctx) {
5130                 file_lines_free(lines);
5131                 return 1;
5132         }
5133
5134         if (parse_usershare_file(ctx, &sbuf, service_name,
5135                         iService, lines, numlines, &sharepath,
5136                         &comment, &psd, &guest_ok) != USERSHARE_OK) {
5137                 talloc_destroy(ctx);
5138                 file_lines_free(lines);
5139                 return -1;
5140         }
5141
5142         file_lines_free(lines);
5143
5144         /* Everything ok - add the service possibly using a template. */
5145         if (iService < 0) {
5146                 const service *sp = &sDefault;
5147                 if (snum_template != -1) {
5148                         sp = ServicePtrs[snum_template];
5149                 }
5150
5151                 if ((iService = add_a_service(sp, service_name)) < 0) {
5152                         DEBUG(0, ("process_usershare_file: Failed to add "
5153                                 "new service %s\n", service_name));
5154                         talloc_destroy(ctx);
5155                         return -1;
5156                 }
5157
5158                 /* Read only is controlled by usershare ACL below. */
5159                 ServicePtrs[iService]->bRead_only = False;
5160         }
5161
5162         /* Write the ACL of the new/modified share. */
5163         if (!set_share_security(service_name, psd)) {
5164                  DEBUG(0, ("process_usershare_file: Failed to set share "
5165                         "security for user share %s\n",
5166                         service_name ));
5167                 lp_remove_service(iService);
5168                 talloc_destroy(ctx);
5169                 return -1;
5170         }
5171
5172         /* If from a template it may be marked invalid. */
5173         ServicePtrs[iService]->valid = True;
5174
5175         /* Set the service as a valid usershare. */
5176         ServicePtrs[iService]->usershare = USERSHARE_VALID;
5177
5178         /* Set guest access. */
5179         if (lp_usershare_allow_guests()) {
5180                 ServicePtrs[iService]->bGuest_ok = guest_ok;
5181         }
5182
5183         /* And note when it was loaded. */
5184         ServicePtrs[iService]->usershare_last_mod = sbuf.st_mtime;
5185         string_set(&ServicePtrs[iService]->szPath, sharepath);
5186         string_set(&ServicePtrs[iService]->comment, comment);
5187
5188         talloc_destroy(ctx);
5189
5190         return iService;
5191 }
5192
5193 /***************************************************************************
5194  Checks if a usershare entry has been modified since last load.
5195 ***************************************************************************/
5196
5197 static bool usershare_exists(int iService, time_t *last_mod)
5198 {
5199         SMB_STRUCT_STAT lsbuf;
5200         const char *usersharepath = Globals.szUsersharePath;
5201         char *fname;
5202
5203         if (asprintf(&fname, "%s/%s",
5204                                 usersharepath,
5205                                 ServicePtrs[iService]->szService) < 0) {
5206                 return false;
5207         }
5208
5209         if (sys_lstat(fname, &lsbuf) != 0) {
5210                 SAFE_FREE(fname);
5211                 return false;
5212         }
5213
5214         if (!S_ISREG(lsbuf.st_mode)) {
5215                 SAFE_FREE(fname);
5216                 return false;
5217         }
5218
5219         SAFE_FREE(fname);
5220         *last_mod = lsbuf.st_mtime;
5221         return true;
5222 }
5223
5224 /***************************************************************************
5225  Load a usershare service by name. Returns a valid servicenumber or -1.
5226 ***************************************************************************/
5227
5228 int load_usershare_service(const char *servicename)
5229 {
5230         SMB_STRUCT_STAT sbuf;
5231         const char *usersharepath = Globals.szUsersharePath;
5232         int max_user_shares = Globals.iUsershareMaxShares;
5233         int snum_template = -1;
5234
5235         if (*usersharepath == 0 ||  max_user_shares == 0) {
5236                 return -1;
5237         }
5238
5239         if (sys_stat(usersharepath, &sbuf) != 0) {
5240                 DEBUG(0,("load_usershare_service: stat of %s failed. %s\n",
5241                         usersharepath, strerror(errno) ));
5242                 return -1;
5243         }
5244
5245         if (!S_ISDIR(sbuf.st_mode)) {
5246                 DEBUG(0,("load_usershare_service: %s is not a directory.\n",
5247                         usersharepath ));
5248                 return -1;
5249         }
5250
5251         /*
5252          * This directory must be owned by root, and have the 't' bit set.
5253          * It also must not be writable by "other".
5254          */
5255
5256 #ifdef S_ISVTX
5257         if (sbuf.st_uid != 0 || !(sbuf.st_mode & S_ISVTX) || (sbuf.st_mode & S_IWOTH)) {
5258 #else
5259         if (sbuf.st_uid != 0 || (sbuf.st_mode & S_IWOTH)) {
5260 #endif
5261                 DEBUG(0,("load_usershare_service: directory %s is not owned by root "
5262                         "or does not have the sticky bit 't' set or is writable by anyone.\n",
5263                         usersharepath ));
5264                 return -1;
5265         }
5266
5267         /* Ensure the template share exists if it's set. */
5268         if (Globals.szUsershareTemplateShare[0]) {
5269                 /* We can't use lp_servicenumber here as we are recommending that
5270                    template shares have -valid=False set. */
5271                 for (snum_template = iNumServices - 1; snum_template >= 0; snum_template--) {
5272                         if (ServicePtrs[snum_template]->szService &&
5273                                         strequal(ServicePtrs[snum_template]->szService,
5274                                                 Globals.szUsershareTemplateShare)) {
5275                                 break;
5276                         }
5277                 }
5278
5279                 if (snum_template == -1) {
5280                         DEBUG(0,("load_usershare_service: usershare template share %s "
5281                                 "does not exist.\n",
5282                                 Globals.szUsershareTemplateShare ));
5283                         return -1;
5284                 }
5285         }
5286
5287         return process_usershare_file(usersharepath, servicename, snum_template);
5288 }
5289
5290 /***************************************************************************
5291  Load all user defined shares from the user share directory.
5292  We only do this if we're enumerating the share list.
5293  This is the function that can delete usershares that have
5294  been removed.
5295 ***************************************************************************/
5296
5297 int load_usershare_shares(void)
5298 {
5299         SMB_STRUCT_DIR *dp;
5300         SMB_STRUCT_STAT sbuf;
5301         SMB_STRUCT_DIRENT *de;
5302         int num_usershares = 0;
5303         int max_user_shares = Globals.iUsershareMaxShares;
5304         unsigned int num_dir_entries, num_bad_dir_entries, num_tmp_dir_entries;
5305         unsigned int allowed_bad_entries = ((2*max_user_shares)/10);
5306         unsigned int allowed_tmp_entries = ((2*max_user_shares)/10);
5307         int iService;
5308         int snum_template = -1;
5309         const char *usersharepath = Globals.szUsersharePath;
5310         int ret = lp_numservices();
5311
5312         if (max_user_shares == 0 || *usersharepath == '\0') {
5313                 return lp_numservices();
5314         }
5315
5316         if (sys_stat(usersharepath, &sbuf) != 0) {
5317                 DEBUG(0,("load_usershare_shares: stat of %s failed. %s\n",
5318                         usersharepath, strerror(errno) ));
5319                 return ret;
5320         }
5321
5322         /*
5323          * This directory must be owned by root, and have the 't' bit set.
5324          * It also must not be writable by "other".
5325          */
5326
5327 #ifdef S_ISVTX
5328         if (sbuf.st_uid != 0 || !(sbuf.st_mode & S_ISVTX) || (sbuf.st_mode & S_IWOTH)) {
5329 #else
5330         if (sbuf.st_uid != 0 || (sbuf.st_mode & S_IWOTH)) {
5331 #endif
5332                 DEBUG(0,("load_usershare_shares: directory %s is not owned by root "
5333                         "or does not have the sticky bit 't' set or is writable by anyone.\n",
5334                         usersharepath ));
5335                 return ret;
5336         }
5337
5338         /* Ensure the template share exists if it's set. */
5339         if (Globals.szUsershareTemplateShare[0]) {
5340                 /* We can't use lp_servicenumber here as we are recommending that
5341                    template shares have -valid=False set. */
5342                 for (snum_template = iNumServices - 1; snum_template >= 0; snum_template--) {
5343                         if (ServicePtrs[snum_template]->szService &&
5344                                         strequal(ServicePtrs[snum_template]->szService,
5345                                                 Globals.szUsershareTemplateShare)) {
5346                                 break;
5347                         }
5348                 }
5349
5350                 if (snum_template == -1) {
5351                         DEBUG(0,("load_usershare_shares: usershare template share %s "
5352                                 "does not exist.\n",
5353                                 Globals.szUsershareTemplateShare ));
5354                         return ret;
5355                 }
5356         }
5357
5358         /* Mark all existing usershares as pending delete. */
5359         for (iService = iNumServices - 1; iService >= 0; iService--) {
5360                 if (VALID(iService) && ServicePtrs[iService]->usershare) {
5361                         ServicePtrs[iService]->usershare = USERSHARE_PENDING_DELETE;
5362                 }
5363         }
5364
5365         dp = sys_opendir(usersharepath);
5366         if (!dp) {
5367                 DEBUG(0,("load_usershare_shares:: failed to open directory %s. %s\n",
5368                         usersharepath, strerror(errno) ));
5369                 return ret;
5370         }
5371
5372         for (num_dir_entries = 0, num_bad_dir_entries = 0, num_tmp_dir_entries = 0;
5373                         (de = sys_readdir(dp));
5374                         num_dir_entries++ ) {
5375                 int r;
5376                 const char *n = de->d_name;
5377
5378                 /* Ignore . and .. */
5379                 if (*n == '.') {
5380                         if ((n[1] == '\0') || (n[1] == '.' && n[2] == '\0')) {
5381                                 continue;
5382                         }
5383                 }
5384
5385                 if (n[0] == ':') {
5386                         /* Temporary file used when creating a share. */
5387                         num_tmp_dir_entries++;
5388                 }
5389
5390                 /* Allow 20% tmp entries. */
5391                 if (num_tmp_dir_entries > allowed_tmp_entries) {
5392                         DEBUG(0,("load_usershare_shares: too many temp entries (%u) "
5393                                 "in directory %s\n",
5394                                 num_tmp_dir_entries, usersharepath));
5395                         break;
5396                 }
5397
5398                 r = process_usershare_file(usersharepath, n, snum_template);
5399                 if (r == 0) {
5400                         /* Update the services count. */
5401                         num_usershares++;
5402                         if (num_usershares >= max_user_shares) {
5403                                 DEBUG(0,("load_usershare_shares: max user shares reached "
5404                                         "on file %s in directory %s\n",
5405                                         n, usersharepath ));
5406                                 break;
5407                         }
5408                 } else if (r == -1) {
5409                         num_bad_dir_entries++;
5410                 }
5411
5412                 /* Allow 20% bad entries. */
5413                 if (num_bad_dir_entries > allowed_bad_entries) {
5414                         DEBUG(0,("load_usershare_shares: too many bad entries (%u) "
5415                                 "in directory %s\n",
5416                                 num_bad_dir_entries, usersharepath));
5417                         break;
5418                 }
5419
5420                 /* Allow 20% bad entries. */
5421                 if (num_dir_entries > max_user_shares + allowed_bad_entries) {
5422                         DEBUG(0,("load_usershare_shares: too many total entries (%u) "
5423                         "in directory %s\n",
5424                         num_dir_entries, usersharepath));
5425                         break;
5426                 }
5427         }
5428
5429         sys_closedir(dp);
5430
5431         /* Sweep through and delete any non-refreshed usershares that are
5432            not currently in use. */
5433         for (iService = iNumServices - 1; iService >= 0; iService--) {
5434                 if (VALID(iService) && (ServicePtrs[iService]->usershare == USERSHARE_PENDING_DELETE)) {
5435                         if (conn_snum_used(iService)) {
5436                                 continue;
5437                         }
5438                         /* Remove from the share ACL db. */
5439                         DEBUG(10,("load_usershare_shares: Removing deleted usershare %s\n",
5440                                 lp_servicename(iService) ));
5441                         delete_share_security(lp_servicename(iService));
5442                         free_service_byindex(iService);
5443                 }
5444         }
5445
5446         return lp_numservices();
5447 }
5448
5449 /********************************************************
5450  Destroy global resources allocated in this file
5451 ********************************************************/
5452
5453 void gfree_loadparm(void)
5454 {
5455         struct file_lists *f;
5456         struct file_lists *next;
5457         int i;
5458
5459         /* Free the file lists */
5460
5461         f = file_lists;
5462         while( f ) {
5463                 next = f->next;
5464                 SAFE_FREE( f->name );
5465                 SAFE_FREE( f->subfname );
5466                 SAFE_FREE( f );
5467                 f = next;
5468         }
5469
5470         /* Free resources allocated to services */
5471
5472         for ( i = 0; i < iNumServices; i++ ) {
5473                 if ( VALID(i) ) {
5474                         free_service_byindex(i);
5475                 }
5476         }
5477
5478         SAFE_FREE( ServicePtrs );
5479         iNumServices = 0;
5480
5481         /* Now release all resources allocated to global
5482            parameters and the default service */
5483
5484         for (i = 0; parm_table[i].label; i++) 
5485         {
5486                 if ( parm_table[i].type == P_STRING 
5487                         || parm_table[i].type == P_USTRING ) 
5488                 {
5489                         string_free( (char**)parm_table[i].ptr );
5490                 }
5491                 else if (parm_table[i].type == P_LIST) {
5492                         TALLOC_FREE( *((char***)parm_table[i].ptr) );
5493                 }
5494         }
5495 }
5496
5497 /***************************************************************************
5498  Load the services array from the services file. Return True on success, 
5499  False on failure.
5500 ***************************************************************************/
5501
5502 bool lp_load(const char *pszFname,
5503              bool global_only,
5504              bool save_defaults,
5505              bool add_ipc,
5506              bool initialize_globals)
5507 {
5508         char *n2 = NULL;
5509         bool bRetval;
5510         param_opt_struct *data, *pdata;
5511
5512         bRetval = False;
5513
5514         DEBUG(3, ("lp_load: refreshing parameters\n"));
5515
5516         bInGlobalSection = True;
5517         bGlobalOnly = global_only;
5518
5519         init_globals(! initialize_globals);
5520         debug_init();
5521
5522         if (save_defaults) {
5523                 init_locals();
5524                 lp_save_defaults();
5525         }
5526
5527         if (Globals.param_opt != NULL) {
5528                 data = Globals.param_opt;
5529                 while (data) {
5530                         string_free(&data->key);
5531                         string_free(&data->value);
5532                         TALLOC_FREE(data->list);
5533                         pdata = data->next;
5534                         SAFE_FREE(data);
5535                         data = pdata;
5536                 }
5537                 Globals.param_opt = NULL;
5538         }
5539
5540         if (lp_config_backend() == CONFIG_BACKEND_FILE) {
5541                 n2 = alloc_sub_basic(get_current_username(),
5542                                         current_user_info.domain,
5543                                         pszFname);
5544                 if (!n2) {
5545                         smb_panic("lp_load: out of memory");
5546                 }
5547
5548                 add_to_file_list(pszFname, n2);
5549
5550                 /* We get sections first, so have to start 'behind' to make up */
5551                 iServiceIndex = -1;
5552                 bRetval = pm_process(n2, do_section, do_parameter);
5553                 SAFE_FREE(n2);
5554
5555                 /* finish up the last section */
5556                 DEBUG(4, ("pm_process() returned %s\n", BOOLSTR(bRetval)));
5557                 if (bRetval) {
5558                         if (iServiceIndex >= 0) {
5559                                 bRetval = service_ok(iServiceIndex);
5560                         }
5561                 }
5562
5563                 if (lp_config_backend() == CONFIG_BACKEND_REGISTRY) {
5564                         /*
5565                          * We need to use this extra global variable here to
5566                          * survive restart: init_globals usese this as a default
5567                          * for ConfigBackend. Otherwise, init_globals would
5568                          *  send us into an endless loop here.
5569                          */
5570                         config_backend = CONFIG_BACKEND_REGISTRY;
5571                         /* start over */
5572                         init_globals(false);
5573                         return lp_load(pszFname, global_only, save_defaults,
5574                                        add_ipc, initialize_globals);
5575                 }
5576         } else if (lp_config_backend() == CONFIG_BACKEND_REGISTRY) {
5577                 bRetval = process_registry_globals(do_parameter);
5578         } else {
5579                 DEBUG(0, ("Illegal config  backend given: %d\n",
5580                           lp_config_backend()));
5581                 bRetval = false;
5582         }
5583
5584         lp_add_auto_services(lp_auto_services());
5585
5586         if (add_ipc) {
5587                 /* When 'restrict anonymous = 2' guest connections to ipc$
5588                    are denied */
5589                 lp_add_ipc("IPC$", (lp_restrict_anonymous() < 2));
5590                 if ( lp_enable_asu_support() ) {
5591                         lp_add_ipc("ADMIN$", false);
5592                 }
5593         }
5594
5595         set_server_role();
5596         set_default_server_announce_type();
5597         set_allowed_client_auth();
5598
5599         bLoaded = True;
5600
5601         /* Now we check bWINSsupport and set szWINSserver to 127.0.0.1 */
5602         /* if bWINSsupport is true and we are in the client            */
5603         if (in_client && Globals.bWINSsupport) {
5604                 lp_do_parameter(GLOBAL_SECTION_SNUM, "wins server", "127.0.0.1");
5605         }
5606
5607         init_iconv();
5608
5609         return (bRetval);
5610 }
5611
5612 /***************************************************************************
5613  Reset the max number of services.
5614 ***************************************************************************/
5615
5616 void lp_resetnumservices(void)
5617 {
5618         iNumServices = 0;
5619 }
5620
5621 /***************************************************************************
5622  Return the max number of services.
5623 ***************************************************************************/
5624
5625 int lp_numservices(void)
5626 {
5627         return (iNumServices);
5628 }
5629
5630 /***************************************************************************
5631 Display the contents of the services array in human-readable form.
5632 ***************************************************************************/
5633
5634 void lp_dump(FILE *f, bool show_defaults, int maxtoprint)
5635 {
5636         int iService;
5637
5638         if (show_defaults)
5639                 defaults_saved = False;
5640
5641         dump_globals(f);
5642
5643         dump_a_service(&sDefault, f);
5644
5645         for (iService = 0; iService < maxtoprint; iService++) {
5646                 fprintf(f,"\n");
5647                 lp_dump_one(f, show_defaults, iService);
5648         }
5649 }
5650
5651 /***************************************************************************
5652 Display the contents of one service in human-readable form.
5653 ***************************************************************************/
5654
5655 void lp_dump_one(FILE * f, bool show_defaults, int snum)
5656 {
5657         if (VALID(snum)) {
5658                 if (ServicePtrs[snum]->szService[0] == '\0')
5659                         return;
5660                 dump_a_service(ServicePtrs[snum], f);
5661         }
5662 }
5663
5664 /***************************************************************************
5665 Return the number of the service with the given name, or -1 if it doesn't
5666 exist. Note that this is a DIFFERENT ANIMAL from the internal function
5667 getservicebyname()! This works ONLY if all services have been loaded, and
5668 does not copy the found service.
5669 ***************************************************************************/
5670
5671 int lp_servicenumber(const char *pszServiceName)
5672 {
5673         int iService;
5674         fstring serviceName;
5675         
5676         if (!pszServiceName) {
5677                 return GLOBAL_SECTION_SNUM;
5678         }
5679         
5680         for (iService = iNumServices - 1; iService >= 0; iService--) {
5681                 if (VALID(iService) && ServicePtrs[iService]->szService) {
5682                         /*
5683                          * The substitution here is used to support %U is
5684                          * service names
5685                          */
5686                         fstrcpy(serviceName, ServicePtrs[iService]->szService);
5687                         standard_sub_basic(get_current_username(),
5688                                            current_user_info.domain,
5689                                            serviceName,sizeof(serviceName));
5690                         if (strequal(serviceName, pszServiceName)) {
5691                                 break;
5692                         }
5693                 }
5694         }
5695
5696         if (iService >= 0 && ServicePtrs[iService]->usershare == USERSHARE_VALID) {
5697                 time_t last_mod;
5698
5699                 if (!usershare_exists(iService, &last_mod)) {
5700                         /* Remove the share security tdb entry for it. */
5701                         delete_share_security(lp_servicename(iService));
5702                         /* Remove it from the array. */
5703                         free_service_byindex(iService);
5704                         /* Doesn't exist anymore. */
5705                         return GLOBAL_SECTION_SNUM;
5706                 }
5707
5708                 /* Has it been modified ? If so delete and reload. */
5709                 if (ServicePtrs[iService]->usershare_last_mod < last_mod) {
5710                         /* Remove it from the array. */
5711                         free_service_byindex(iService);
5712                         /* and now reload it. */
5713                         iService = load_usershare_service(pszServiceName);
5714                 }
5715         }
5716
5717         if (iService < 0) {
5718                 DEBUG(7,("lp_servicenumber: couldn't find %s\n", pszServiceName));
5719                 return GLOBAL_SECTION_SNUM;
5720         }
5721
5722         return (iService);
5723 }
5724
5725 bool share_defined(const char *service_name)
5726 {
5727         return (lp_servicenumber(service_name) != -1);
5728 }
5729
5730 struct share_params *get_share_params(TALLOC_CTX *mem_ctx,
5731                                       const char *sharename)
5732 {
5733         struct share_params *result;
5734         char *sname;
5735         int snum;
5736
5737         if (!(sname = SMB_STRDUP(sharename))) {
5738                 return NULL;
5739         }
5740
5741         snum = find_service(sname);
5742         SAFE_FREE(sname);
5743
5744         if (snum < 0) {
5745                 return NULL;
5746         }
5747
5748         if (!(result = TALLOC_P(mem_ctx, struct share_params))) {
5749                 DEBUG(0, ("talloc failed\n"));
5750                 return NULL;
5751         }
5752
5753         result->service = snum;
5754         return result;
5755 }
5756
5757 struct share_iterator *share_list_all(TALLOC_CTX *mem_ctx)
5758 {
5759         struct share_iterator *result;
5760
5761         if (!(result = TALLOC_P(mem_ctx, struct share_iterator))) {
5762                 DEBUG(0, ("talloc failed\n"));
5763                 return NULL;
5764         }
5765
5766         result->next_id = 0;
5767         return result;
5768 }
5769
5770 struct share_params *next_share(struct share_iterator *list)
5771 {
5772         struct share_params *result;
5773
5774         while (!lp_snum_ok(list->next_id) &&
5775                (list->next_id < lp_numservices())) {
5776                 list->next_id += 1;
5777         }
5778
5779         if (list->next_id >= lp_numservices()) {
5780                 return NULL;
5781         }
5782
5783         if (!(result = TALLOC_P(list, struct share_params))) {
5784                 DEBUG(0, ("talloc failed\n"));
5785                 return NULL;
5786         }
5787
5788         result->service = list->next_id;
5789         list->next_id += 1;
5790         return result;
5791 }
5792
5793 struct share_params *next_printer(struct share_iterator *list)
5794 {
5795         struct share_params *result;
5796
5797         while ((result = next_share(list)) != NULL) {
5798                 if (lp_print_ok(result->service)) {
5799                         break;
5800                 }
5801         }
5802         return result;
5803 }
5804
5805 /*
5806  * This is a hack for a transition period until we transformed all code from
5807  * service numbers to struct share_params.
5808  */
5809
5810 struct share_params *snum2params_static(int snum)
5811 {
5812         static struct share_params result;
5813         result.service = snum;
5814         return &result;
5815 }
5816
5817 /*******************************************************************
5818  A useful volume label function. 
5819 ********************************************************************/
5820
5821 const char *volume_label(int snum)
5822 {
5823         char *ret;
5824         const char *label = lp_volume(snum);
5825         if (!*label) {
5826                 label = lp_servicename(snum);
5827         }
5828                 
5829         /* This returns a 33 byte guarenteed null terminated string. */
5830         ret = talloc_strndup(talloc_tos(), label, 32);
5831         if (!ret) {
5832                 return "";
5833         }               
5834         return ret;
5835 }
5836
5837 /*******************************************************************
5838  Set the server type we will announce as via nmbd.
5839 ********************************************************************/
5840
5841 static void set_default_server_announce_type(void)
5842 {
5843         default_server_announce = 0;
5844         default_server_announce |= SV_TYPE_WORKSTATION;
5845         default_server_announce |= SV_TYPE_SERVER;
5846         default_server_announce |= SV_TYPE_SERVER_UNIX;
5847
5848         /* note that the flag should be set only if we have a 
5849            printer service but nmbd doesn't actually load the 
5850            services so we can't tell   --jerry */
5851
5852         default_server_announce |= SV_TYPE_PRINTQ_SERVER;
5853
5854         switch (lp_announce_as()) {
5855                 case ANNOUNCE_AS_NT_SERVER:
5856                         default_server_announce |= SV_TYPE_SERVER_NT;
5857                         /* fall through... */
5858                 case ANNOUNCE_AS_NT_WORKSTATION:
5859                         default_server_announce |= SV_TYPE_NT;
5860                         break;
5861                 case ANNOUNCE_AS_WIN95:
5862                         default_server_announce |= SV_TYPE_WIN95_PLUS;
5863                         break;
5864                 case ANNOUNCE_AS_WFW:
5865                         default_server_announce |= SV_TYPE_WFW;
5866                         break;
5867                 default:
5868                         break;
5869         }
5870
5871         switch (lp_server_role()) {
5872                 case ROLE_DOMAIN_MEMBER:
5873                         default_server_announce |= SV_TYPE_DOMAIN_MEMBER;
5874                         break;
5875                 case ROLE_DOMAIN_PDC:
5876                         default_server_announce |= SV_TYPE_DOMAIN_CTRL;
5877                         break;
5878                 case ROLE_DOMAIN_BDC:
5879                         default_server_announce |= SV_TYPE_DOMAIN_BAKCTRL;
5880                         break;
5881                 case ROLE_STANDALONE:
5882                 default:
5883                         break;
5884         }
5885         if (lp_time_server())
5886                 default_server_announce |= SV_TYPE_TIME_SOURCE;
5887
5888         if (lp_host_msdfs())
5889                 default_server_announce |= SV_TYPE_DFS_SERVER;
5890 }
5891
5892 /***********************************************************
5893  returns role of Samba server
5894 ************************************************************/
5895
5896 int lp_server_role(void)
5897 {
5898         return server_role;
5899 }
5900
5901 /***********************************************************
5902  If we are PDC then prefer us as DMB
5903 ************************************************************/
5904
5905 bool lp_domain_master(void)
5906 {
5907         if (Globals.iDomainMaster == Auto)
5908                 return (lp_server_role() == ROLE_DOMAIN_PDC);
5909
5910         return (bool)Globals.iDomainMaster;
5911 }
5912
5913 /***********************************************************
5914  If we are DMB then prefer us as LMB
5915 ************************************************************/
5916
5917 bool lp_preferred_master(void)
5918 {
5919         if (Globals.iPreferredMaster == Auto)
5920                 return (lp_local_master() && lp_domain_master());
5921
5922         return (bool)Globals.iPreferredMaster;
5923 }
5924
5925 /*******************************************************************
5926  Remove a service.
5927 ********************************************************************/
5928
5929 void lp_remove_service(int snum)
5930 {
5931         ServicePtrs[snum]->valid = False;
5932         invalid_services[num_invalid_services++] = snum;
5933 }
5934
5935 /*******************************************************************
5936  Copy a service.
5937 ********************************************************************/
5938
5939 void lp_copy_service(int snum, const char *new_name)
5940 {
5941         do_section(new_name);
5942         if (snum >= 0) {
5943                 snum = lp_servicenumber(new_name);
5944                 if (snum >= 0)
5945                         lp_do_parameter(snum, "copy", lp_servicename(snum));
5946         }
5947 }
5948
5949
5950 /*******************************************************************
5951  Get the default server type we will announce as via nmbd.
5952 ********************************************************************/
5953
5954 int lp_default_server_announce(void)
5955 {
5956         return default_server_announce;
5957 }
5958
5959 /*******************************************************************
5960  Split the announce version into major and minor numbers.
5961 ********************************************************************/
5962
5963 int lp_major_announce_version(void)
5964 {
5965         static bool got_major = False;
5966         static int major_version = DEFAULT_MAJOR_VERSION;
5967         char *vers;
5968         char *p;
5969
5970         if (got_major)
5971                 return major_version;
5972
5973         got_major = True;
5974         if ((vers = lp_announce_version()) == NULL)
5975                 return major_version;
5976
5977         if ((p = strchr_m(vers, '.')) == 0)
5978                 return major_version;
5979
5980         *p = '\0';
5981         major_version = atoi(vers);
5982         return major_version;
5983 }
5984
5985 int lp_minor_announce_version(void)
5986 {
5987         static bool got_minor = False;
5988         static int minor_version = DEFAULT_MINOR_VERSION;
5989         char *vers;
5990         char *p;
5991
5992         if (got_minor)
5993                 return minor_version;
5994
5995         got_minor = True;
5996         if ((vers = lp_announce_version()) == NULL)
5997                 return minor_version;
5998
5999         if ((p = strchr_m(vers, '.')) == 0)
6000                 return minor_version;
6001
6002         p++;
6003         minor_version = atoi(p);
6004         return minor_version;
6005 }
6006
6007 /***********************************************************
6008  Set the global name resolution order (used in smbclient).
6009 ************************************************************/
6010
6011 void lp_set_name_resolve_order(const char *new_order)
6012 {
6013         string_set(&Globals.szNameResolveOrder, new_order);
6014 }
6015
6016 const char *lp_printername(int snum)
6017 {
6018         const char *ret = _lp_printername(snum);
6019         if (ret == NULL || (ret != NULL && *ret == '\0'))
6020                 ret = lp_const_servicename(snum);
6021
6022         return ret;
6023 }
6024
6025
6026 /***********************************************************
6027  Allow daemons such as winbindd to fix their logfile name.
6028 ************************************************************/
6029
6030 void lp_set_logfile(const char *name)
6031 {
6032         string_set(&Globals.szLogFile, name);
6033         debug_set_logfile(name);
6034 }
6035
6036 /*******************************************************************
6037  Return the max print jobs per queue.
6038 ********************************************************************/
6039
6040 int lp_maxprintjobs(int snum)
6041 {
6042         int maxjobs = LP_SNUM_OK(snum) ? ServicePtrs[snum]->iMaxPrintJobs : sDefault.iMaxPrintJobs;
6043         if (maxjobs <= 0 || maxjobs >= PRINT_MAX_JOBID)
6044                 maxjobs = PRINT_MAX_JOBID - 1;
6045
6046         return maxjobs;
6047 }
6048
6049 const char *lp_printcapname(void)
6050 {
6051         if ((Globals.szPrintcapname != NULL) &&
6052             (Globals.szPrintcapname[0] != '\0'))
6053                 return Globals.szPrintcapname;
6054
6055         if (sDefault.iPrinting == PRINT_CUPS) {
6056 #ifdef HAVE_CUPS
6057                 return "cups";
6058 #else
6059                 return "lpstat";
6060 #endif
6061         }
6062
6063         if (sDefault.iPrinting == PRINT_BSD)
6064                 return "/etc/printcap";
6065
6066         return PRINTCAP_NAME;
6067 }
6068
6069 /*******************************************************************
6070  Ensure we don't use sendfile if server smb signing is active.
6071 ********************************************************************/
6072
6073 static uint32 spoolss_state;
6074
6075 bool lp_disable_spoolss( void )
6076 {
6077         if ( spoolss_state == SVCCTL_STATE_UNKNOWN )
6078                 spoolss_state = _lp_disable_spoolss() ? SVCCTL_STOPPED : SVCCTL_RUNNING;
6079
6080         return spoolss_state == SVCCTL_STOPPED ? True : False;
6081 }
6082
6083 void lp_set_spoolss_state( uint32 state )
6084 {
6085         SMB_ASSERT( (state == SVCCTL_STOPPED) || (state == SVCCTL_RUNNING) );
6086
6087         spoolss_state = state;
6088 }
6089
6090 uint32 lp_get_spoolss_state( void )
6091 {
6092         return lp_disable_spoolss() ? SVCCTL_STOPPED : SVCCTL_RUNNING;
6093 }
6094
6095 /*******************************************************************
6096  Ensure we don't use sendfile if server smb signing is active.
6097 ********************************************************************/
6098
6099 bool lp_use_sendfile(int snum)
6100 {
6101         /* Using sendfile blows the brains out of any DOS or Win9x TCP stack... JRA. */
6102         if (Protocol < PROTOCOL_NT1) {
6103                 return False;
6104         }
6105         return (_lp_use_sendfile(snum) &&
6106                         (get_remote_arch() != RA_WIN95) &&
6107                         !srv_is_signing_active());
6108 }
6109
6110 /*******************************************************************
6111  Turn off sendfile if we find the underlying OS doesn't support it.
6112 ********************************************************************/
6113
6114 void set_use_sendfile(int snum, bool val)
6115 {
6116         if (LP_SNUM_OK(snum))
6117                 ServicePtrs[snum]->bUseSendfile = val;
6118         else
6119                 sDefault.bUseSendfile = val;
6120 }
6121
6122 /*******************************************************************
6123  Turn off storing DOS attributes if this share doesn't support it.
6124 ********************************************************************/
6125
6126 void set_store_dos_attributes(int snum, bool val)
6127 {
6128         if (!LP_SNUM_OK(snum))
6129                 return;
6130         ServicePtrs[(snum)]->bStoreDosAttributes = val;
6131 }
6132
6133 void lp_set_mangling_method(const char *new_method)
6134 {
6135         string_set(&Globals.szManglingMethod, new_method);
6136 }
6137
6138 /*******************************************************************
6139  Global state for POSIX pathname processing.
6140 ********************************************************************/
6141
6142 static bool posix_pathnames;
6143
6144 bool lp_posix_pathnames(void)
6145 {
6146         return posix_pathnames;
6147 }
6148
6149 /*******************************************************************
6150  Change everything needed to ensure POSIX pathname processing (currently
6151  not much).
6152 ********************************************************************/
6153
6154 void lp_set_posix_pathnames(void)
6155 {
6156         posix_pathnames = True;
6157 }
6158
6159 /*******************************************************************
6160  Global state for POSIX lock processing - CIFS unix extensions.
6161 ********************************************************************/
6162
6163 bool posix_default_lock_was_set;
6164 static enum brl_flavour posix_cifsx_locktype; /* By default 0 == WINDOWS_LOCK */
6165
6166 enum brl_flavour lp_posix_cifsu_locktype(files_struct *fsp)
6167 {
6168         if (posix_default_lock_was_set) {
6169                 return posix_cifsx_locktype;
6170         } else {
6171                 return fsp->posix_open ? POSIX_LOCK : WINDOWS_LOCK;
6172         }
6173 }
6174
6175 /*******************************************************************
6176 ********************************************************************/
6177
6178 void lp_set_posix_default_cifsx_readwrite_locktype(enum brl_flavour val)
6179 {
6180         posix_default_lock_was_set = True;
6181         posix_cifsx_locktype = val;
6182 }
6183
6184 int lp_min_receive_file_size(void)
6185 {
6186         if (Globals.iminreceivefile < 0) {
6187                 return 0;
6188         }
6189         return MIN(Globals.iminreceivefile, BUFFER_SIZE);
6190 }