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