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