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