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