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