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