r23471: Here's a rough patch for expanding domain group membership
[vlendec/samba-autobuild/.git] / source3 / param / loadparm.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Parameter loading functions
4    Copyright (C) Karl Auer 1993-1998
5
6    Largely re-written by Andrew Tridgell, September 1994
7
8    Copyright (C) Simo Sorce 2001
9    Copyright (C) Alexander Bokovoy 2002
10    Copyright (C) Stefan (metze) Metzmacher 2002
11    Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2003
12    
13    This program is free software; you can redistribute it and/or modify
14    it under the terms of the GNU General Public License as published by
15    the Free Software Foundation; either version 2 of the License, or
16    (at your option) any later version.
17    
18    This program is distributed in the hope that it will be useful,
19    but WITHOUT ANY WARRANTY; without even the implied warranty of
20    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21    GNU General Public License for more details.
22    
23    You should have received a copy of the GNU General Public License
24    along with this program; if not, write to the Free Software
25    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 */
27
28 /*
29  *  Load parameters.
30  *
31  *  This module provides suitable callback functions for the params
32  *  module. It builds the internal table of service details which is
33  *  then used by the rest of the server.
34  *
35  * To add a parameter:
36  *
37  * 1) add it to the global or service structure definition
38  * 2) add it to the parm_table
39  * 3) add it to the list of available functions (eg: using FN_GLOBAL_STRING())
40  * 4) If it's a global then initialise it in init_globals. If a local
41  *    (ie. service) parameter then initialise it in the sDefault structure
42  *  
43  *
44  * Notes:
45  *   The configuration file is processed sequentially for speed. It is NOT
46  *   accessed randomly as happens in 'real' Windows. For this reason, there
47  *   is a fair bit of sequence-dependent code here - ie., code which assumes
48  *   that certain things happen before others. In particular, the code which
49  *   happens at the boundary between sections is delicately poised, so be
50  *   careful!
51  *
52  */
53
54 #include "includes.h"
55
56 BOOL in_client = False;         /* Not in the client by default */
57 BOOL bLoaded = False;
58
59 extern 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.bWinbindRefreshTickets = False;
1648         Globals.bWinbindOfflineLogon = False;
1649
1650         Globals.iIdmapCacheTime = 900; /* 15 minutes by default */
1651         Globals.iIdmapNegativeCacheTime = 120; /* 2 minutes by default */
1652
1653         Globals.bPassdbExpandExplicit = False;
1654
1655         Globals.name_cache_timeout = 660; /* In seconds */
1656
1657         Globals.bUseSpnego = True;
1658         Globals.bClientUseSpnego = True;
1659
1660         Globals.client_signing = Auto;
1661         Globals.server_signing = False;
1662
1663         Globals.bDeferSharingViolations = True;
1664         string_set(&Globals.smb_ports, SMB_PORTS);
1665
1666         Globals.bEnablePrivileges = True;
1667         Globals.bHostMSDfs        = True;
1668         Globals.bASUSupport       = False;
1669         
1670         /* User defined shares. */
1671         pstrcpy(s, dyn_LOCKDIR);
1672         pstrcat(s, "/usershares");
1673         string_set(&Globals.szUsersharePath, s);
1674         string_set(&Globals.szUsershareTemplateShare, "");
1675         Globals.iUsershareMaxShares = 0;
1676         /* By default disallow sharing of directories not owned by the sharer. */
1677         Globals.bUsershareOwnerOnly = True;
1678         /* By default disallow guest access to usershares. */
1679         Globals.bUsershareAllowGuests = False;
1680
1681         Globals.iKeepalive = DEFAULT_KEEPALIVE;
1682
1683         /* By default no shares out of the registry */
1684         Globals.bRegistryShares = False;
1685 }
1686
1687 static TALLOC_CTX *lp_talloc;
1688
1689 /******************************************************************* a
1690  Free up temporary memory - called from the main loop.
1691 ********************************************************************/
1692
1693 void lp_TALLOC_FREE(void)
1694 {
1695         if (!lp_talloc)
1696                 return;
1697         TALLOC_FREE(lp_talloc);
1698         lp_talloc = NULL;
1699 }
1700
1701 TALLOC_CTX *tmp_talloc_ctx(void)
1702 {
1703         if (lp_talloc == NULL) {
1704                 lp_talloc = talloc_init("tmp_talloc_ctx");
1705         }
1706
1707         if (lp_talloc == NULL) {
1708                 smb_panic("Could not create temporary talloc context\n");
1709         }
1710
1711         return lp_talloc;
1712 }
1713
1714 /*******************************************************************
1715  Convenience routine to grab string parameters into temporary memory
1716  and run standard_sub_basic on them. The buffers can be written to by
1717  callers without affecting the source string.
1718 ********************************************************************/
1719
1720 static char *lp_string(const char *s)
1721 {
1722         char *ret, *tmpstr;
1723
1724         /* The follow debug is useful for tracking down memory problems
1725            especially if you have an inner loop that is calling a lp_*()
1726            function that returns a string.  Perhaps this debug should be
1727            present all the time? */
1728
1729 #if 0
1730         DEBUG(10, ("lp_string(%s)\n", s));
1731 #endif
1732
1733         if (!lp_talloc)
1734                 lp_talloc = talloc_init("lp_talloc");
1735
1736         tmpstr = alloc_sub_basic(get_current_username(),
1737                                  current_user_info.domain, s);
1738         if (trim_char(tmpstr, '\"', '\"')) {
1739                 if (strchr(tmpstr,'\"') != NULL) {
1740                         SAFE_FREE(tmpstr);
1741                         tmpstr = alloc_sub_basic(get_current_username(),
1742                                                  current_user_info.domain, s);
1743                 }
1744         }
1745         ret = talloc_strdup(lp_talloc, tmpstr);
1746         SAFE_FREE(tmpstr);
1747                         
1748         return (ret);
1749 }
1750
1751 /*
1752    In this section all the functions that are used to access the 
1753    parameters from the rest of the program are defined 
1754 */
1755
1756 #define FN_GLOBAL_STRING(fn_name,ptr) \
1757  char *fn_name(void) {return(lp_string(*(char **)(ptr) ? *(char **)(ptr) : ""));}
1758 #define FN_GLOBAL_CONST_STRING(fn_name,ptr) \
1759  const char *fn_name(void) {return(*(const char **)(ptr) ? *(const char **)(ptr) : "");}
1760 #define FN_GLOBAL_LIST(fn_name,ptr) \
1761  const char **fn_name(void) {return(*(const char ***)(ptr));}
1762 #define FN_GLOBAL_BOOL(fn_name,ptr) \
1763  BOOL fn_name(void) {return(*(BOOL *)(ptr));}
1764 #define FN_GLOBAL_CHAR(fn_name,ptr) \
1765  char fn_name(void) {return(*(char *)(ptr));}
1766 #define FN_GLOBAL_INTEGER(fn_name,ptr) \
1767  int fn_name(void) {return(*(int *)(ptr));}
1768
1769 #define FN_LOCAL_STRING(fn_name,val) \
1770  char *fn_name(int i) {return(lp_string((LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val));}
1771 #define FN_LOCAL_CONST_STRING(fn_name,val) \
1772  const char *fn_name(int i) {return (const char *)((LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val);}
1773 #define FN_LOCAL_LIST(fn_name,val) \
1774  const char **fn_name(int i) {return(const char **)(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1775 #define FN_LOCAL_BOOL(fn_name,val) \
1776  BOOL fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1777 #define FN_LOCAL_INTEGER(fn_name,val) \
1778  int fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1779
1780 #define FN_LOCAL_PARM_BOOL(fn_name,val) \
1781  BOOL fn_name(const struct share_params *p) {return(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
1782 #define FN_LOCAL_PARM_INTEGER(fn_name,val) \
1783  int fn_name(const struct share_params *p) {return(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
1784 #define FN_LOCAL_PARM_STRING(fn_name,val) \
1785  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));}
1786 #define FN_LOCAL_CHAR(fn_name,val) \
1787  char fn_name(const struct share_params *p) {return(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
1788
1789 FN_GLOBAL_STRING(lp_smb_ports, &Globals.smb_ports)
1790 FN_GLOBAL_STRING(lp_dos_charset, &Globals.dos_charset)
1791 FN_GLOBAL_STRING(lp_unix_charset, &Globals.unix_charset)
1792 FN_GLOBAL_STRING(lp_display_charset, &Globals.display_charset)
1793 FN_GLOBAL_STRING(lp_logfile, &Globals.szLogFile)
1794 FN_GLOBAL_STRING(lp_configfile, &Globals.szConfigFile)
1795 FN_GLOBAL_STRING(lp_smb_passwd_file, &Globals.szSMBPasswdFile)
1796 FN_GLOBAL_STRING(lp_private_dir, &Globals.szPrivateDir)
1797 FN_GLOBAL_STRING(lp_serverstring, &Globals.szServerString)
1798 FN_GLOBAL_INTEGER(lp_printcap_cache_time, &Globals.PrintcapCacheTime)
1799 FN_GLOBAL_STRING(lp_addport_cmd, &Globals.szAddPortCommand)
1800 FN_GLOBAL_STRING(lp_enumports_cmd, &Globals.szEnumPortsCommand)
1801 FN_GLOBAL_STRING(lp_addprinter_cmd, &Globals.szAddPrinterCommand)
1802 FN_GLOBAL_STRING(lp_deleteprinter_cmd, &Globals.szDeletePrinterCommand)
1803 FN_GLOBAL_STRING(lp_os2_driver_map, &Globals.szOs2DriverMap)
1804 FN_GLOBAL_STRING(lp_lockdir, &Globals.szLockDir)
1805 FN_GLOBAL_STRING(lp_piddir, &Globals.szPidDir)
1806 FN_GLOBAL_STRING(lp_mangling_method, &Globals.szManglingMethod)
1807 FN_GLOBAL_INTEGER(lp_mangle_prefix, &Globals.mangle_prefix)
1808 FN_GLOBAL_STRING(lp_utmpdir, &Globals.szUtmpDir)
1809 FN_GLOBAL_STRING(lp_wtmpdir, &Globals.szWtmpDir)
1810 FN_GLOBAL_BOOL(lp_utmp, &Globals.bUtmp)
1811 FN_GLOBAL_STRING(lp_rootdir, &Globals.szRootdir)
1812 FN_GLOBAL_STRING(lp_defaultservice, &Globals.szDefaultService)
1813 FN_GLOBAL_STRING(lp_msg_command, &Globals.szMsgCommand)
1814 FN_GLOBAL_STRING(lp_get_quota_command, &Globals.szGetQuota)
1815 FN_GLOBAL_STRING(lp_set_quota_command, &Globals.szSetQuota)
1816 FN_GLOBAL_STRING(lp_auto_services, &Globals.szAutoServices)
1817 FN_GLOBAL_STRING(lp_passwd_program, &Globals.szPasswdProgram)
1818 FN_GLOBAL_STRING(lp_passwd_chat, &Globals.szPasswdChat)
1819 FN_GLOBAL_STRING(lp_passwordserver, &Globals.szPasswordServer)
1820 FN_GLOBAL_STRING(lp_name_resolve_order, &Globals.szNameResolveOrder)
1821 FN_GLOBAL_STRING(lp_realm, &Globals.szRealm)
1822 FN_GLOBAL_CONST_STRING(lp_afs_username_map, &Globals.szAfsUsernameMap)
1823 FN_GLOBAL_INTEGER(lp_afs_token_lifetime, &Globals.iAfsTokenLifetime)
1824 FN_GLOBAL_STRING(lp_log_nt_token_command, &Globals.szLogNtTokenCommand)
1825 FN_GLOBAL_STRING(lp_username_map, &Globals.szUsernameMap)
1826 FN_GLOBAL_CONST_STRING(lp_logon_script, &Globals.szLogonScript)
1827 FN_GLOBAL_CONST_STRING(lp_logon_path, &Globals.szLogonPath)
1828 FN_GLOBAL_CONST_STRING(lp_logon_drive, &Globals.szLogonDrive)
1829 FN_GLOBAL_CONST_STRING(lp_logon_home, &Globals.szLogonHome)
1830 FN_GLOBAL_STRING(lp_remote_announce, &Globals.szRemoteAnnounce)
1831 FN_GLOBAL_STRING(lp_remote_browse_sync, &Globals.szRemoteBrowseSync)
1832 FN_GLOBAL_LIST(lp_wins_server_list, &Globals.szWINSservers)
1833 FN_GLOBAL_LIST(lp_interfaces, &Globals.szInterfaces)
1834 FN_GLOBAL_STRING(lp_socket_address, &Globals.szSocketAddress)
1835 FN_GLOBAL_STRING(lp_nis_home_map_name, &Globals.szNISHomeMapName)
1836 static FN_GLOBAL_STRING(lp_announce_version, &Globals.szAnnounceVersion)
1837 FN_GLOBAL_LIST(lp_netbios_aliases, &Globals.szNetbiosAliases)
1838 /* FN_GLOBAL_STRING(lp_passdb_backend, &Globals.szPassdbBackend)
1839  * lp_passdb_backend() should be replace by the this macro again after
1840  * some releases.
1841  * */
1842 const char *lp_passdb_backend(void)
1843 {
1844         char *delim, *quote;
1845
1846         delim = strchr( Globals.szPassdbBackend, ' ');
1847         /* no space at all */
1848         if (delim == NULL) {
1849                 goto out;
1850         }
1851
1852         quote = strchr(Globals.szPassdbBackend, '"');
1853         /* no quote char or non in the first part */
1854         if (quote == NULL || quote > delim) {
1855                 *delim = '\0';
1856                 goto warn;
1857         }
1858
1859         quote = strchr(quote+1, '"');
1860         if (quote == NULL) {
1861                 DEBUG(0, ("WARNING: Your 'passdb backend' configuration is invalid due to a missing second \" char.\n"));
1862                 goto out;
1863         } else if (*(quote+1) == '\0') {
1864                 /* space, fitting quote char, and one backend only */
1865                 goto out;
1866         } else {
1867                 /* terminate string after the fitting quote char */
1868                 *(quote+1) = '\0';
1869         }
1870
1871 warn:
1872         DEBUG(0, ("WARNING: Your 'passdb backend' configuration includes multiple backends.  This\n"
1873                 "is deprecated since Samba 3.0.23.  Please check WHATSNEW.txt or the section 'Passdb\n"
1874                 "Changes' from the ChangeNotes as part of the Samba HOWTO collection.  Only the first\n"
1875                 "backend (%s) is used.  The rest is ignored.\n", Globals.szPassdbBackend));
1876
1877 out:
1878         return Globals.szPassdbBackend;
1879 }
1880 FN_GLOBAL_LIST(lp_preload_modules, &Globals.szPreloadModules)
1881 FN_GLOBAL_STRING(lp_panic_action, &Globals.szPanicAction)
1882 FN_GLOBAL_STRING(lp_adduser_script, &Globals.szAddUserScript)
1883 FN_GLOBAL_STRING(lp_renameuser_script, &Globals.szRenameUserScript)
1884 FN_GLOBAL_STRING(lp_deluser_script, &Globals.szDelUserScript)
1885
1886 FN_GLOBAL_CONST_STRING(lp_guestaccount, &Globals.szGuestaccount)
1887 FN_GLOBAL_STRING(lp_addgroup_script, &Globals.szAddGroupScript)
1888 FN_GLOBAL_STRING(lp_delgroup_script, &Globals.szDelGroupScript)
1889 FN_GLOBAL_STRING(lp_addusertogroup_script, &Globals.szAddUserToGroupScript)
1890 FN_GLOBAL_STRING(lp_deluserfromgroup_script, &Globals.szDelUserFromGroupScript)
1891 FN_GLOBAL_STRING(lp_setprimarygroup_script, &Globals.szSetPrimaryGroupScript)
1892
1893 FN_GLOBAL_STRING(lp_addmachine_script, &Globals.szAddMachineScript)
1894
1895 FN_GLOBAL_STRING(lp_shutdown_script, &Globals.szShutdownScript)
1896 FN_GLOBAL_STRING(lp_abort_shutdown_script, &Globals.szAbortShutdownScript)
1897 FN_GLOBAL_STRING(lp_username_map_script, &Globals.szUsernameMapScript)
1898
1899 FN_GLOBAL_STRING(lp_check_password_script, &Globals.szCheckPasswordScript)
1900
1901 FN_GLOBAL_STRING(lp_wins_hook, &Globals.szWINSHook)
1902 FN_GLOBAL_CONST_STRING(lp_template_homedir, &Globals.szTemplateHomedir)
1903 FN_GLOBAL_CONST_STRING(lp_template_shell, &Globals.szTemplateShell)
1904 FN_GLOBAL_CONST_STRING(lp_winbind_separator, &Globals.szWinbindSeparator)
1905 FN_GLOBAL_INTEGER(lp_acl_compatibility, &Globals.iAclCompat)
1906 FN_GLOBAL_BOOL(lp_winbind_enum_users, &Globals.bWinbindEnumUsers)
1907 FN_GLOBAL_BOOL(lp_winbind_enum_groups, &Globals.bWinbindEnumGroups)
1908 FN_GLOBAL_BOOL(lp_winbind_use_default_domain, &Globals.bWinbindUseDefaultDomain)
1909 FN_GLOBAL_BOOL(lp_winbind_trusted_domains_only, &Globals.bWinbindTrustedDomainsOnly)
1910 FN_GLOBAL_BOOL(lp_winbind_nested_groups, &Globals.bWinbindNestedGroups)
1911 FN_GLOBAL_INTEGER(lp_winbind_expand_groups, &Globals.winbind_expand_groups)
1912 FN_GLOBAL_BOOL(lp_winbind_refresh_tickets, &Globals.bWinbindRefreshTickets)
1913 FN_GLOBAL_BOOL(lp_winbind_offline_logon, &Globals.bWinbindOfflineLogon)
1914 FN_GLOBAL_BOOL(lp_winbind_normalize_names, &Globals.bWinbindNormalizeNames)
1915 FN_GLOBAL_BOOL(lp_winbind_rpc_only, &Globals.bWinbindRpcOnly)
1916
1917 FN_GLOBAL_LIST(lp_idmap_domains, &Globals.szIdmapDomains)
1918 FN_GLOBAL_LIST(lp_idmap_backend, &Globals.szIdmapBackend) /* deprecated */
1919 FN_GLOBAL_STRING(lp_idmap_alloc_backend, &Globals.szIdmapAllocBackend)
1920 FN_GLOBAL_INTEGER(lp_idmap_cache_time, &Globals.iIdmapCacheTime)
1921 FN_GLOBAL_INTEGER(lp_idmap_negative_cache_time, &Globals.iIdmapNegativeCacheTime)
1922 FN_GLOBAL_INTEGER(lp_keepalive, &Globals.iKeepalive)
1923 FN_GLOBAL_BOOL(lp_passdb_expand_explicit, &Globals.bPassdbExpandExplicit)
1924
1925 FN_GLOBAL_STRING(lp_ldap_suffix, &Globals.szLdapSuffix)
1926 FN_GLOBAL_STRING(lp_ldap_admin_dn, &Globals.szLdapAdminDn)
1927 FN_GLOBAL_INTEGER(lp_ldap_ssl, &Globals.ldap_ssl)
1928 FN_GLOBAL_INTEGER(lp_ldap_passwd_sync, &Globals.ldap_passwd_sync)
1929 FN_GLOBAL_BOOL(lp_ldap_delete_dn, &Globals.ldap_delete_dn)
1930 FN_GLOBAL_INTEGER(lp_ldap_replication_sleep, &Globals.ldap_replication_sleep)
1931 FN_GLOBAL_INTEGER(lp_ldap_timeout, &Globals.ldap_timeout)
1932 FN_GLOBAL_INTEGER(lp_ldap_page_size, &Globals.ldap_page_size)
1933 FN_GLOBAL_STRING(lp_add_share_cmd, &Globals.szAddShareCommand)
1934 FN_GLOBAL_STRING(lp_change_share_cmd, &Globals.szChangeShareCommand)
1935 FN_GLOBAL_STRING(lp_delete_share_cmd, &Globals.szDeleteShareCommand)
1936 FN_GLOBAL_STRING(lp_usershare_path, &Globals.szUsersharePath)
1937 FN_GLOBAL_LIST(lp_usershare_prefix_allow_list, &Globals.szUsersharePrefixAllowList)
1938 FN_GLOBAL_LIST(lp_usershare_prefix_deny_list, &Globals.szUsersharePrefixDenyList)
1939
1940 FN_GLOBAL_LIST(lp_eventlog_list, &Globals.szEventLogs)
1941
1942 FN_GLOBAL_BOOL(lp_registry_shares, &Globals.bRegistryShares)
1943 FN_GLOBAL_BOOL(lp_usershare_allow_guests, &Globals.bUsershareAllowGuests)
1944 FN_GLOBAL_BOOL(lp_usershare_owner_only, &Globals.bUsershareOwnerOnly)
1945 FN_GLOBAL_BOOL(lp_disable_netbios, &Globals.bDisableNetbios)
1946 FN_GLOBAL_BOOL(lp_reset_on_zero_vc, &Globals.bResetOnZeroVC)
1947 FN_GLOBAL_BOOL(lp_ms_add_printer_wizard, &Globals.bMsAddPrinterWizard)
1948 FN_GLOBAL_BOOL(lp_dns_proxy, &Globals.bDNSproxy)
1949 FN_GLOBAL_BOOL(lp_wins_support, &Globals.bWINSsupport)
1950 FN_GLOBAL_BOOL(lp_we_are_a_wins_server, &Globals.bWINSsupport)
1951 FN_GLOBAL_BOOL(lp_wins_proxy, &Globals.bWINSproxy)
1952 FN_GLOBAL_BOOL(lp_local_master, &Globals.bLocalMaster)
1953 FN_GLOBAL_BOOL(lp_domain_logons, &Globals.bDomainLogons)
1954 FN_GLOBAL_BOOL(lp_load_printers, &Globals.bLoadPrinters)
1955 FN_GLOBAL_BOOL(lp_readbmpx, &Globals.bReadbmpx)
1956 FN_GLOBAL_BOOL(lp_readraw, &Globals.bReadRaw)
1957 FN_GLOBAL_BOOL(lp_large_readwrite, &Globals.bLargeReadwrite)
1958 FN_GLOBAL_BOOL(lp_writeraw, &Globals.bWriteRaw)
1959 FN_GLOBAL_BOOL(lp_null_passwords, &Globals.bNullPasswords)
1960 FN_GLOBAL_BOOL(lp_obey_pam_restrictions, &Globals.bObeyPamRestrictions)
1961 FN_GLOBAL_BOOL(lp_encrypted_passwords, &Globals.bEncryptPasswords)
1962 FN_GLOBAL_BOOL(lp_update_encrypted, &Globals.bUpdateEncrypt)
1963 FN_GLOBAL_INTEGER(lp_client_schannel, &Globals.clientSchannel)
1964 FN_GLOBAL_INTEGER(lp_server_schannel, &Globals.serverSchannel)
1965 FN_GLOBAL_BOOL(lp_syslog_only, &Globals.bSyslogOnly)
1966 FN_GLOBAL_BOOL(lp_timestamp_logs, &Globals.bTimestampLogs)
1967 FN_GLOBAL_BOOL(lp_debug_prefix_timestamp, &Globals.bDebugPrefixTimestamp)
1968 FN_GLOBAL_BOOL(lp_debug_hires_timestamp, &Globals.bDebugHiresTimestamp)
1969 FN_GLOBAL_BOOL(lp_debug_pid, &Globals.bDebugPid)
1970 FN_GLOBAL_BOOL(lp_debug_uid, &Globals.bDebugUid)
1971 FN_GLOBAL_BOOL(lp_enable_core_files, &Globals.bEnableCoreFiles)
1972 FN_GLOBAL_BOOL(lp_browse_list, &Globals.bBrowseList)
1973 FN_GLOBAL_BOOL(lp_nis_home_map, &Globals.bNISHomeMap)
1974 static FN_GLOBAL_BOOL(lp_time_server, &Globals.bTimeServer)
1975 FN_GLOBAL_BOOL(lp_bind_interfaces_only, &Globals.bBindInterfacesOnly)
1976 FN_GLOBAL_BOOL(lp_pam_password_change, &Globals.bPamPasswordChange)
1977 FN_GLOBAL_BOOL(lp_unix_password_sync, &Globals.bUnixPasswdSync)
1978 FN_GLOBAL_BOOL(lp_passwd_chat_debug, &Globals.bPasswdChatDebug)
1979 FN_GLOBAL_INTEGER(lp_passwd_chat_timeout, &Globals.iPasswdChatTimeout)
1980 FN_GLOBAL_BOOL(lp_nt_pipe_support, &Globals.bNTPipeSupport)
1981 FN_GLOBAL_BOOL(lp_nt_status_support, &Globals.bNTStatusSupport)
1982 FN_GLOBAL_BOOL(lp_stat_cache, &Globals.bStatCache)
1983 FN_GLOBAL_INTEGER(lp_max_stat_cache_size, &Globals.iMaxStatCacheSize)
1984 FN_GLOBAL_BOOL(lp_allow_trusted_domains, &Globals.bAllowTrustedDomains)
1985 FN_GLOBAL_INTEGER(lp_restrict_anonymous, &Globals.restrict_anonymous)
1986 FN_GLOBAL_BOOL(lp_lanman_auth, &Globals.bLanmanAuth)
1987 FN_GLOBAL_BOOL(lp_ntlm_auth, &Globals.bNTLMAuth)
1988 FN_GLOBAL_BOOL(lp_client_plaintext_auth, &Globals.bClientPlaintextAuth)
1989 FN_GLOBAL_BOOL(lp_client_lanman_auth, &Globals.bClientLanManAuth)
1990 FN_GLOBAL_BOOL(lp_client_ntlmv2_auth, &Globals.bClientNTLMv2Auth)
1991 FN_GLOBAL_BOOL(lp_host_msdfs, &Globals.bHostMSDfs)
1992 FN_GLOBAL_BOOL(lp_kernel_oplocks, &Globals.bKernelOplocks)
1993 FN_GLOBAL_BOOL(lp_enhanced_browsing, &Globals.enhanced_browsing)
1994 FN_GLOBAL_BOOL(lp_use_mmap, &Globals.bUseMmap)
1995 FN_GLOBAL_BOOL(lp_unix_extensions, &Globals.bUnixExtensions)
1996 FN_GLOBAL_BOOL(lp_use_spnego, &Globals.bUseSpnego)
1997 FN_GLOBAL_BOOL(lp_client_use_spnego, &Globals.bClientUseSpnego)
1998 FN_GLOBAL_BOOL(lp_hostname_lookups, &Globals.bHostnameLookups)
1999 FN_LOCAL_PARM_BOOL(lp_change_notify, bChangeNotify)
2000 FN_LOCAL_PARM_BOOL(lp_kernel_change_notify, bKernelChangeNotify)
2001 FN_GLOBAL_BOOL(lp_use_kerberos_keytab, &Globals.bUseKerberosKeytab)
2002 FN_GLOBAL_BOOL(lp_defer_sharing_violations, &Globals.bDeferSharingViolations)
2003 FN_GLOBAL_BOOL(lp_enable_privileges, &Globals.bEnablePrivileges)
2004 FN_GLOBAL_BOOL(lp_enable_asu_support, &Globals.bASUSupport)
2005 FN_GLOBAL_INTEGER(lp_os_level, &Globals.os_level)
2006 FN_GLOBAL_INTEGER(lp_max_ttl, &Globals.max_ttl)
2007 FN_GLOBAL_INTEGER(lp_max_wins_ttl, &Globals.max_wins_ttl)
2008 FN_GLOBAL_INTEGER(lp_min_wins_ttl, &Globals.min_wins_ttl)
2009 FN_GLOBAL_INTEGER(lp_max_log_size, &Globals.max_log_size)
2010 FN_GLOBAL_INTEGER(lp_max_open_files, &Globals.max_open_files)
2011 FN_GLOBAL_INTEGER(lp_open_files_db_hash_size, &Globals.open_files_db_hash_size)
2012 FN_GLOBAL_INTEGER(lp_maxxmit, &Globals.max_xmit)
2013 FN_GLOBAL_INTEGER(lp_maxmux, &Globals.max_mux)
2014 FN_GLOBAL_INTEGER(lp_passwordlevel, &Globals.pwordlevel)
2015 FN_GLOBAL_INTEGER(lp_usernamelevel, &Globals.unamelevel)
2016 FN_GLOBAL_INTEGER(lp_deadtime, &Globals.deadtime)
2017 FN_GLOBAL_INTEGER(lp_maxprotocol, &Globals.maxprotocol)
2018 FN_GLOBAL_INTEGER(lp_minprotocol, &Globals.minprotocol)
2019 FN_GLOBAL_INTEGER(lp_security, &Globals.security)
2020 FN_GLOBAL_LIST(lp_auth_methods, &Globals.AuthMethods)
2021 FN_GLOBAL_BOOL(lp_paranoid_server_security, &Globals.paranoid_server_security)
2022 FN_GLOBAL_INTEGER(lp_maxdisksize, &Globals.maxdisksize)
2023 FN_GLOBAL_INTEGER(lp_lpqcachetime, &Globals.lpqcachetime)
2024 FN_GLOBAL_INTEGER(lp_max_smbd_processes, &Globals.iMaxSmbdProcesses)
2025 FN_GLOBAL_INTEGER(_lp_disable_spoolss, &Globals.bDisableSpoolss)
2026 FN_GLOBAL_INTEGER(lp_syslog, &Globals.syslog)
2027 static FN_GLOBAL_INTEGER(lp_announce_as, &Globals.announce_as)
2028 FN_GLOBAL_INTEGER(lp_lm_announce, &Globals.lm_announce)
2029 FN_GLOBAL_INTEGER(lp_lm_interval, &Globals.lm_interval)
2030 FN_GLOBAL_INTEGER(lp_machine_password_timeout, &Globals.machine_password_timeout)
2031 FN_GLOBAL_INTEGER(lp_map_to_guest, &Globals.map_to_guest)
2032 FN_GLOBAL_INTEGER(lp_oplock_break_wait_time, &Globals.oplock_break_wait_time)
2033 FN_GLOBAL_INTEGER(lp_lock_spin_time, &Globals.iLockSpinTime)
2034 FN_GLOBAL_INTEGER(lp_usershare_max_shares, &Globals.iUsershareMaxShares)
2035
2036 FN_LOCAL_STRING(lp_preexec, szPreExec)
2037 FN_LOCAL_STRING(lp_postexec, szPostExec)
2038 FN_LOCAL_STRING(lp_rootpreexec, szRootPreExec)
2039 FN_LOCAL_STRING(lp_rootpostexec, szRootPostExec)
2040 FN_LOCAL_STRING(lp_servicename, szService)
2041 FN_LOCAL_CONST_STRING(lp_const_servicename, szService)
2042 FN_LOCAL_STRING(lp_pathname, szPath)
2043 FN_LOCAL_STRING(lp_dontdescend, szDontdescend)
2044 FN_LOCAL_STRING(lp_username, szUsername)
2045 FN_LOCAL_LIST(lp_invalid_users, szInvalidUsers)
2046 FN_LOCAL_LIST(lp_valid_users, szValidUsers)
2047 FN_LOCAL_LIST(lp_admin_users, szAdminUsers)
2048 FN_GLOBAL_LIST(lp_svcctl_list, &Globals.szServicesList)
2049 FN_LOCAL_STRING(lp_cups_options, szCupsOptions)
2050 FN_GLOBAL_STRING(lp_cups_server, &Globals.szCupsServer)
2051 FN_GLOBAL_STRING(lp_iprint_server, &Globals.szIPrintServer)
2052 FN_GLOBAL_CONST_STRING(lp_ctdbd_socket, &Globals.ctdbdSocket)
2053 FN_GLOBAL_BOOL(lp_clustering, &Globals.clustering);
2054 FN_LOCAL_STRING(lp_printcommand, szPrintcommand)
2055 FN_LOCAL_STRING(lp_lpqcommand, szLpqcommand)
2056 FN_LOCAL_STRING(lp_lprmcommand, szLprmcommand)
2057 FN_LOCAL_STRING(lp_lppausecommand, szLppausecommand)
2058 FN_LOCAL_STRING(lp_lpresumecommand, szLpresumecommand)
2059 FN_LOCAL_STRING(lp_queuepausecommand, szQueuepausecommand)
2060 FN_LOCAL_STRING(lp_queueresumecommand, szQueueresumecommand)
2061 static FN_LOCAL_STRING(_lp_printername, szPrintername)
2062 FN_LOCAL_CONST_STRING(lp_printjob_username, szPrintjobUsername)
2063 FN_LOCAL_LIST(lp_hostsallow, szHostsallow)
2064 FN_LOCAL_LIST(lp_hostsdeny, szHostsdeny)
2065 FN_LOCAL_STRING(lp_magicscript, szMagicScript)
2066 FN_LOCAL_STRING(lp_magicoutput, szMagicOutput)
2067 FN_LOCAL_STRING(lp_comment, comment)
2068 FN_LOCAL_STRING(lp_force_user, force_user)
2069 FN_LOCAL_STRING(lp_force_group, force_group)
2070 FN_LOCAL_LIST(lp_readlist, readlist)
2071 FN_LOCAL_LIST(lp_writelist, writelist)
2072 FN_LOCAL_LIST(lp_printer_admin, printer_admin)
2073 FN_LOCAL_STRING(lp_fstype, fstype)
2074 FN_LOCAL_LIST(lp_vfs_objects, szVfsObjects)
2075 FN_LOCAL_STRING(lp_msdfs_proxy, szMSDfsProxy)
2076 static FN_LOCAL_STRING(lp_volume, volume)
2077 FN_LOCAL_PARM_STRING(lp_mangled_map, szMangledMap)
2078 FN_LOCAL_STRING(lp_veto_files, szVetoFiles)
2079 FN_LOCAL_STRING(lp_hide_files, szHideFiles)
2080 FN_LOCAL_STRING(lp_veto_oplocks, szVetoOplockFiles)
2081 FN_LOCAL_BOOL(lp_msdfs_root, bMSDfsRoot)
2082 FN_LOCAL_STRING(lp_dfree_command, szDfree)
2083 FN_LOCAL_BOOL(lp_autoloaded, autoloaded)
2084 FN_LOCAL_BOOL(lp_preexec_close, bPreexecClose)
2085 FN_LOCAL_BOOL(lp_rootpreexec_close, bRootpreexecClose)
2086 FN_LOCAL_INTEGER(lp_casesensitive, iCaseSensitive)
2087 FN_LOCAL_BOOL(lp_preservecase, bCasePreserve)
2088 FN_LOCAL_BOOL(lp_shortpreservecase, bShortCasePreserve)
2089 FN_LOCAL_BOOL(lp_hide_dot_files, bHideDotFiles)
2090 FN_LOCAL_BOOL(lp_hide_special_files, bHideSpecialFiles)
2091 FN_LOCAL_BOOL(lp_hideunreadable, bHideUnReadable)
2092 FN_LOCAL_BOOL(lp_hideunwriteable_files, bHideUnWriteableFiles)
2093 FN_LOCAL_BOOL(lp_browseable, bBrowseable)
2094 FN_LOCAL_BOOL(lp_readonly, bRead_only)
2095 FN_LOCAL_BOOL(lp_no_set_dir, bNo_set_dir)
2096 FN_LOCAL_BOOL(lp_guest_ok, bGuest_ok)
2097 FN_LOCAL_BOOL(lp_guest_only, bGuest_only)
2098 FN_LOCAL_BOOL(lp_print_ok, bPrint_ok)
2099 FN_LOCAL_BOOL(lp_map_hidden, bMap_hidden)
2100 FN_LOCAL_BOOL(lp_map_archive, bMap_archive)
2101 FN_LOCAL_BOOL(lp_store_dos_attributes, bStoreDosAttributes)
2102 FN_LOCAL_BOOL(lp_dmapi_support, bDmapiSupport)
2103 FN_LOCAL_PARM_BOOL(lp_locking, bLocking)
2104 FN_LOCAL_PARM_INTEGER(lp_strict_locking, iStrictLocking)
2105 FN_LOCAL_PARM_BOOL(lp_posix_locking, bPosixLocking)
2106 FN_LOCAL_BOOL(lp_share_modes, bShareModes)
2107 FN_LOCAL_BOOL(lp_oplocks, bOpLocks)
2108 FN_LOCAL_BOOL(lp_level2_oplocks, bLevel2OpLocks)
2109 FN_LOCAL_BOOL(lp_onlyuser, bOnlyUser)
2110 FN_LOCAL_PARM_BOOL(lp_manglednames, bMangledNames)
2111 FN_LOCAL_BOOL(lp_widelinks, bWidelinks)
2112 FN_LOCAL_BOOL(lp_symlinks, bSymlinks)
2113 FN_LOCAL_BOOL(lp_syncalways, bSyncAlways)
2114 FN_LOCAL_BOOL(lp_strict_allocate, bStrictAllocate)
2115 FN_LOCAL_BOOL(lp_strict_sync, bStrictSync)
2116 FN_LOCAL_BOOL(lp_map_system, bMap_system)
2117 FN_LOCAL_BOOL(lp_delete_readonly, bDeleteReadonly)
2118 FN_LOCAL_BOOL(lp_fake_oplocks, bFakeOplocks)
2119 FN_LOCAL_BOOL(lp_recursive_veto_delete, bDeleteVetoFiles)
2120 FN_LOCAL_BOOL(lp_dos_filemode, bDosFilemode)
2121 FN_LOCAL_BOOL(lp_dos_filetimes, bDosFiletimes)
2122 FN_LOCAL_BOOL(lp_dos_filetime_resolution, bDosFiletimeResolution)
2123 FN_LOCAL_BOOL(lp_fake_dir_create_times, bFakeDirCreateTimes)
2124 FN_LOCAL_BOOL(lp_blocking_locks, bBlockingLocks)
2125 FN_LOCAL_BOOL(lp_inherit_perms, bInheritPerms)
2126 FN_LOCAL_BOOL(lp_inherit_acls, bInheritACLS)
2127 FN_LOCAL_BOOL(lp_inherit_owner, bInheritOwner)
2128 FN_LOCAL_BOOL(lp_use_client_driver, bUseClientDriver)
2129 FN_LOCAL_BOOL(lp_default_devmode, bDefaultDevmode)
2130 FN_LOCAL_BOOL(lp_force_printername, bForcePrintername)
2131 FN_LOCAL_BOOL(lp_nt_acl_support, bNTAclSupport)
2132 FN_LOCAL_BOOL(lp_force_unknown_acl_user, bForceUnknownAclUser)
2133 FN_LOCAL_BOOL(lp_ea_support, bEASupport)
2134 FN_LOCAL_BOOL(_lp_use_sendfile, bUseSendfile)
2135 FN_LOCAL_BOOL(lp_profile_acls, bProfileAcls)
2136 FN_LOCAL_BOOL(lp_map_acl_inherit, bMap_acl_inherit)
2137 FN_LOCAL_BOOL(lp_afs_share, bAfs_Share)
2138 FN_LOCAL_BOOL(lp_acl_check_permissions, bAclCheckPermissions)
2139 FN_LOCAL_BOOL(lp_acl_group_control, bAclGroupControl)
2140 FN_LOCAL_BOOL(lp_acl_map_full_control, bAclMapFullControl)
2141 FN_LOCAL_INTEGER(lp_create_mask, iCreate_mask)
2142 FN_LOCAL_INTEGER(lp_force_create_mode, iCreate_force_mode)
2143 FN_LOCAL_INTEGER(lp_security_mask, iSecurity_mask)
2144 FN_LOCAL_INTEGER(lp_force_security_mode, iSecurity_force_mode)
2145 FN_LOCAL_INTEGER(lp_dir_mask, iDir_mask)
2146 FN_LOCAL_INTEGER(lp_force_dir_mode, iDir_force_mode)
2147 FN_LOCAL_INTEGER(lp_dir_security_mask, iDir_Security_mask)
2148 FN_LOCAL_INTEGER(lp_force_dir_security_mode, iDir_Security_force_mode)
2149 FN_LOCAL_INTEGER(lp_max_connections, iMaxConnections)
2150 FN_LOCAL_INTEGER(lp_defaultcase, iDefaultCase)
2151 FN_LOCAL_INTEGER(lp_minprintspace, iMinPrintSpace)
2152 FN_LOCAL_INTEGER(lp_printing, iPrinting)
2153 FN_LOCAL_INTEGER(lp_max_reported_jobs, iMaxReportedPrintJobs)
2154 FN_LOCAL_INTEGER(lp_oplock_contention_limit, iOplockContentionLimit)
2155 FN_LOCAL_INTEGER(lp_csc_policy, iCSCPolicy)
2156 FN_LOCAL_INTEGER(lp_write_cache_size, iWriteCacheSize)
2157 FN_LOCAL_INTEGER(lp_block_size, iBlock_size)
2158 FN_LOCAL_INTEGER(lp_dfree_cache_time, iDfreeCacheTime)
2159 FN_LOCAL_INTEGER(lp_allocation_roundup_size, iallocation_roundup_size)
2160 FN_LOCAL_INTEGER(lp_aio_read_size, iAioReadSize)
2161 FN_LOCAL_INTEGER(lp_aio_write_size, iAioWriteSize)
2162 FN_LOCAL_INTEGER(lp_map_readonly, iMap_readonly)
2163 FN_LOCAL_CHAR(lp_magicchar, magic_char)
2164 FN_GLOBAL_INTEGER(lp_winbind_cache_time, &Globals.winbind_cache_time)
2165 FN_GLOBAL_LIST(lp_winbind_nss_info, &Globals.szWinbindNssInfo)
2166 FN_GLOBAL_INTEGER(lp_algorithmic_rid_base, &Globals.AlgorithmicRidBase)
2167 FN_GLOBAL_INTEGER(lp_name_cache_timeout, &Globals.name_cache_timeout)
2168 FN_GLOBAL_INTEGER(lp_client_signing, &Globals.client_signing)
2169 FN_GLOBAL_INTEGER(lp_server_signing, &Globals.server_signing)
2170
2171 /* local prototypes */
2172
2173 static int map_parameter(const char *pszParmName);
2174 static BOOL set_boolean(BOOL *pb, const char *pszParmValue);
2175 static int getservicebyname(const char *pszServiceName,
2176                             service * pserviceDest);
2177 static void copy_service(service * pserviceDest,
2178                          service * pserviceSource, BOOL *pcopymapDest);
2179 static BOOL do_parameter(const char *pszParmName, const char *pszParmValue);
2180 static BOOL do_section(const char *pszSectionName);
2181 static void init_copymap(service * pservice);
2182 static BOOL hash_a_service(const char *name, int number);
2183 static void free_service_byindex(int iService);
2184 static char * canonicalize_servicename(const char *name);
2185
2186 /* This is a helper function for parametrical options support. */
2187 /* It returns a pointer to parametrical option value if it exists or NULL otherwise */
2188 /* Actual parametrical functions are quite simple */
2189 static param_opt_struct *get_parametrics(int snum, const char *type, const char *option)
2190 {
2191         BOOL global_section = False;
2192         char* param_key;
2193         param_opt_struct *data;
2194         
2195         if (snum >= iNumServices) return NULL;
2196         
2197         if (snum < 0) { 
2198                 data = Globals.param_opt;
2199                 global_section = True;
2200         } else {
2201                 data = ServicePtrs[snum]->param_opt;
2202         }
2203     
2204         asprintf(&param_key, "%s:%s", type, option);
2205         if (!param_key) {
2206                 DEBUG(0,("asprintf failed!\n"));
2207                 return NULL;
2208         }
2209
2210         while (data) {
2211                 if (strcmp(data->key, param_key) == 0) {
2212                         string_free(&param_key);
2213                         return data;
2214                 }
2215                 data = data->next;
2216         }
2217
2218         if (!global_section) {
2219                 /* Try to fetch the same option but from globals */
2220                 /* but only if we are not already working with Globals */
2221                 data = Globals.param_opt;
2222                 while (data) {
2223                         if (strcmp(data->key, param_key) == 0) {
2224                                 string_free(&param_key);
2225                                 return data;
2226                         }
2227                         data = data->next;
2228                 }
2229         }
2230
2231         string_free(&param_key);
2232         
2233         return NULL;
2234 }
2235
2236
2237 #define MISSING_PARAMETER(name) \
2238     DEBUG(0, ("%s(): value is NULL or empty!\n", #name))
2239
2240 /*******************************************************************
2241 convenience routine to return int parameters.
2242 ********************************************************************/
2243 static int lp_int(const char *s)
2244 {
2245
2246         if (!s || !*s) {
2247                 MISSING_PARAMETER(lp_int);
2248                 return (-1);
2249         }
2250
2251         return (int)strtol(s, NULL, 0);
2252 }
2253
2254 /*******************************************************************
2255 convenience routine to return unsigned long parameters.
2256 ********************************************************************/
2257 static unsigned long lp_ulong(const char *s)
2258 {
2259
2260         if (!s || !*s) {
2261                 MISSING_PARAMETER(lp_ulong);
2262                 return (0);
2263         }
2264
2265         return strtoul(s, NULL, 0);
2266 }
2267
2268 /*******************************************************************
2269 convenience routine to return boolean parameters.
2270 ********************************************************************/
2271 static BOOL lp_bool(const char *s)
2272 {
2273         BOOL ret = False;
2274
2275         if (!s || !*s) {
2276                 MISSING_PARAMETER(lp_bool);
2277                 return False;
2278         }
2279         
2280         if (!set_boolean(&ret,s)) {
2281                 DEBUG(0,("lp_bool(%s): value is not boolean!\n",s));
2282                 return False;
2283         }
2284
2285         return ret;
2286 }
2287
2288 /*******************************************************************
2289 convenience routine to return enum parameters.
2290 ********************************************************************/
2291 static int lp_enum(const char *s,const struct enum_list *_enum)
2292 {
2293         int i;
2294
2295         if (!s || !*s || !_enum) {
2296                 MISSING_PARAMETER(lp_enum);
2297                 return (-1);
2298         }
2299         
2300         for (i=0; _enum[i].name; i++) {
2301                 if (strequal(_enum[i].name,s))
2302                         return _enum[i].value;
2303         }
2304
2305         DEBUG(0,("lp_enum(%s,enum): value is not in enum_list!\n",s));
2306         return (-1);
2307 }
2308
2309 #undef MISSING_PARAMETER
2310
2311 /* DO NOT USE lp_parm_string ANYMORE!!!!
2312  * use lp_parm_const_string or lp_parm_talloc_string
2313  *
2314  * lp_parm_string is only used to let old modules find this symbol
2315  */
2316 #undef lp_parm_string
2317  char *lp_parm_string(const char *servicename, const char *type, const char *option);
2318  char *lp_parm_string(const char *servicename, const char *type, const char *option)
2319 {
2320         return lp_parm_talloc_string(lp_servicenumber(servicename), type, option, NULL);
2321 }
2322
2323 /* Return parametric option from a given service. Type is a part of option before ':' */
2324 /* Parametric option has following syntax: 'Type: option = value' */
2325 /* the returned value is talloced in lp_talloc */
2326 char *lp_parm_talloc_string(int snum, const char *type, const char *option, const char *def)
2327 {
2328         param_opt_struct *data = get_parametrics(snum, type, option);
2329         
2330         if (data == NULL||data->value==NULL) {
2331                 if (def) {
2332                         return lp_string(def);
2333                 } else {
2334                         return NULL;
2335                 }
2336         }
2337
2338         return lp_string(data->value);
2339 }
2340
2341 /* Return parametric option from a given service. Type is a part of option before ':' */
2342 /* Parametric option has following syntax: 'Type: option = value' */
2343 const char *lp_parm_const_string(int snum, const char *type, const char *option, const char *def)
2344 {
2345         param_opt_struct *data = get_parametrics(snum, type, option);
2346         
2347         if (data == NULL||data->value==NULL)
2348                 return def;
2349                 
2350         return data->value;
2351 }
2352
2353 /* Return parametric option from a given service. Type is a part of option before ':' */
2354 /* Parametric option has following syntax: 'Type: option = value' */
2355
2356 const char **lp_parm_string_list(int snum, const char *type, const char *option, const char **def)
2357 {
2358         param_opt_struct *data = get_parametrics(snum, type, option);
2359
2360         if (data == NULL||data->value==NULL)
2361                 return (const char **)def;
2362                 
2363         if (data->list==NULL) {
2364                 data->list = str_list_make(data->value, NULL);
2365         }
2366
2367         return (const char **)data->list;
2368 }
2369
2370 /* Return parametric option from a given service. Type is a part of option before ':' */
2371 /* Parametric option has following syntax: 'Type: option = value' */
2372
2373 int lp_parm_int(int snum, const char *type, const char *option, int def)
2374 {
2375         param_opt_struct *data = get_parametrics(snum, type, option);
2376         
2377         if (data && data->value && *data->value)
2378                 return lp_int(data->value);
2379
2380         return def;
2381 }
2382
2383 /* Return parametric option from a given service. Type is a part of option before ':' */
2384 /* Parametric option has following syntax: 'Type: option = value' */
2385
2386 unsigned long lp_parm_ulong(int snum, const char *type, const char *option, unsigned long def)
2387 {
2388         param_opt_struct *data = get_parametrics(snum, type, option);
2389         
2390         if (data && data->value && *data->value)
2391                 return lp_ulong(data->value);
2392
2393         return def;
2394 }
2395
2396 /* Return parametric option from a given service. Type is a part of option before ':' */
2397 /* Parametric option has following syntax: 'Type: option = value' */
2398
2399 BOOL lp_parm_bool(int snum, const char *type, const char *option, BOOL def)
2400 {
2401         param_opt_struct *data = get_parametrics(snum, type, option);
2402         
2403         if (data && data->value && *data->value)
2404                 return lp_bool(data->value);
2405
2406         return def;
2407 }
2408
2409 /* Return parametric option from a given service. Type is a part of option before ':' */
2410 /* Parametric option has following syntax: 'Type: option = value' */
2411
2412 int lp_parm_enum(int snum, const char *type, const char *option,
2413                  const struct enum_list *_enum, int def)
2414 {
2415         param_opt_struct *data = get_parametrics(snum, type, option);
2416         
2417         if (data && data->value && *data->value && _enum)
2418                 return lp_enum(data->value, _enum);
2419
2420         return def;
2421 }
2422
2423
2424 /***************************************************************************
2425  Initialise a service to the defaults.
2426 ***************************************************************************/
2427
2428 static void init_service(service * pservice)
2429 {
2430         memset((char *)pservice, '\0', sizeof(service));
2431         copy_service(pservice, &sDefault, NULL);
2432 }
2433
2434 /***************************************************************************
2435  Free the dynamically allocated parts of a service struct.
2436 ***************************************************************************/
2437
2438 static void free_service(service *pservice)
2439 {
2440         int i;
2441         param_opt_struct *data, *pdata;
2442         if (!pservice)
2443                 return;
2444
2445         if (pservice->szService)
2446                 DEBUG(5, ("free_service: Freeing service %s\n",
2447                        pservice->szService));
2448
2449         string_free(&pservice->szService);
2450         SAFE_FREE(pservice->copymap);
2451
2452         for (i = 0; parm_table[i].label; i++) {
2453                 if ((parm_table[i].type == P_STRING ||
2454                      parm_table[i].type == P_USTRING) &&
2455                     parm_table[i].p_class == P_LOCAL)
2456                         string_free((char **)
2457                                     (((char *)pservice) +
2458                                      PTR_DIFF(parm_table[i].ptr, &sDefault)));
2459                 else if (parm_table[i].type == P_LIST &&
2460                          parm_table[i].p_class == P_LOCAL)
2461                              str_list_free((char ***)
2462                                             (((char *)pservice) +
2463                                              PTR_DIFF(parm_table[i].ptr, &sDefault)));
2464         }
2465
2466         data = pservice->param_opt;
2467         if (data)
2468                 DEBUG(5,("Freeing parametrics:\n"));
2469         while (data) {
2470                 DEBUG(5,("[%s = %s]\n", data->key, data->value));
2471                 string_free(&data->key);
2472                 string_free(&data->value);
2473                 str_list_free(&data->list);
2474                 pdata = data->next;
2475                 SAFE_FREE(data);
2476                 data = pdata;
2477         }
2478
2479         ZERO_STRUCTP(pservice);
2480 }
2481
2482
2483 /***************************************************************************
2484  remove a service indexed in the ServicePtrs array from the ServiceHash
2485  and free the dynamically allocated parts
2486 ***************************************************************************/
2487
2488 static void free_service_byindex(int idx)
2489 {
2490         if ( !LP_SNUM_OK(idx) ) 
2491                 return;
2492
2493         ServicePtrs[idx]->valid = False;
2494         invalid_services[num_invalid_services++] = idx;
2495
2496         /* we have to cleanup the hash record */
2497
2498         if (ServicePtrs[idx]->szService) {
2499                 char *canon_name = canonicalize_servicename( ServicePtrs[idx]->szService );
2500                 
2501                 tdb_delete_bystring(ServiceHash, canon_name );
2502         }
2503
2504         free_service(ServicePtrs[idx]);
2505 }
2506
2507 /***************************************************************************
2508  Add a new service to the services array initialising it with the given 
2509  service. 
2510 ***************************************************************************/
2511
2512 static int add_a_service(const service *pservice, const char *name)
2513 {
2514         int i;
2515         service tservice;
2516         int num_to_alloc = iNumServices + 1;
2517         param_opt_struct *data, *pdata;
2518
2519         tservice = *pservice;
2520
2521         /* it might already exist */
2522         if (name) {
2523                 i = getservicebyname(name, NULL);
2524                 if (i >= 0) {
2525                         /* Clean all parametric options for service */
2526                         /* They will be added during parsing again */
2527                         data = ServicePtrs[i]->param_opt;
2528                         while (data) {
2529                                 string_free(&data->key);
2530                                 string_free(&data->value);
2531                                 str_list_free(&data->list);
2532                                 pdata = data->next;
2533                                 SAFE_FREE(data);
2534                                 data = pdata;
2535                         }
2536                         ServicePtrs[i]->param_opt = NULL;
2537                         return (i);
2538                 }
2539         }
2540
2541         /* find an invalid one */
2542         i = iNumServices;
2543         if (num_invalid_services > 0) {
2544                 i = invalid_services[--num_invalid_services];
2545         }
2546
2547         /* if not, then create one */
2548         if (i == iNumServices) {
2549                 service **tsp;
2550                 int *tinvalid;
2551                 
2552                 tsp = SMB_REALLOC_ARRAY_KEEP_OLD_ON_ERROR(ServicePtrs, service *, num_to_alloc);
2553                 if (tsp == NULL) {
2554                         DEBUG(0,("add_a_service: failed to enlarge ServicePtrs!\n"));
2555                         return (-1);
2556                 }
2557                 ServicePtrs = tsp;
2558                 ServicePtrs[iNumServices] = SMB_MALLOC_P(service);
2559                 if (!ServicePtrs[iNumServices]) {
2560                         DEBUG(0,("add_a_service: out of memory!\n"));
2561                         return (-1);
2562                 }
2563                 iNumServices++;
2564
2565                 /* enlarge invalid_services here for now... */
2566                 tinvalid = SMB_REALLOC_ARRAY_KEEP_OLD_ON_ERROR(invalid_services, int,
2567                                              num_to_alloc);
2568                 if (tinvalid == NULL) {
2569                         DEBUG(0,("add_a_service: failed to enlarge "
2570                                  "invalid_services!\n"));
2571                         return (-1);
2572                 }
2573                 invalid_services = tinvalid;
2574         } else {
2575                 free_service_byindex(i);
2576         }
2577
2578         ServicePtrs[i]->valid = True;
2579
2580         init_service(ServicePtrs[i]);
2581         copy_service(ServicePtrs[i], &tservice, NULL);
2582         if (name)
2583                 string_set(&ServicePtrs[i]->szService, name);
2584                 
2585         DEBUG(8,("add_a_service: Creating snum = %d for %s\n", 
2586                 i, ServicePtrs[i]->szService));
2587
2588         if (!hash_a_service(ServicePtrs[i]->szService, i)) {
2589                 return (-1);
2590         }
2591                 
2592         return (i);
2593 }
2594
2595 /***************************************************************************
2596   Canonicalize by converting to lowercase.
2597 ***************************************************************************/
2598
2599 static char *canonicalize_servicename(const char *src)
2600 {
2601         static fstring canon; /* is fstring large enough? */
2602
2603         if ( !src ) {
2604                 DEBUG(0,("canonicalize_servicename: NULL source name!\n"));
2605                 return NULL;
2606         }
2607
2608         fstrcpy( canon, src );
2609         strlower_m( canon );
2610
2611         return canon;
2612 }
2613
2614 /***************************************************************************
2615   Add a name/index pair for the services array to the hash table.
2616 ***************************************************************************/
2617
2618 static BOOL hash_a_service(const char *name, int idx)
2619 {
2620         char *canon_name;
2621
2622         if ( !ServiceHash ) {
2623                 DEBUG(10,("hash_a_service: creating tdb servicehash\n"));
2624                 ServiceHash = tdb_open("servicehash", 1031, TDB_INTERNAL, 
2625                                         (O_RDWR|O_CREAT), 0600);
2626                 if ( !ServiceHash ) {
2627                         DEBUG(0,("hash_a_service: open tdb servicehash failed!\n"));
2628                         return False;
2629                 }
2630         }
2631
2632         DEBUG(10,("hash_a_service: hashing index %d for service name %s\n",
2633                 idx, name));
2634
2635         if ( !(canon_name = canonicalize_servicename( name )) )
2636                 return False;
2637
2638         tdb_store_int32(ServiceHash, canon_name, idx);
2639
2640         return True;
2641 }
2642
2643 /***************************************************************************
2644  Add a new home service, with the specified home directory, defaults coming 
2645  from service ifrom.
2646 ***************************************************************************/
2647
2648 BOOL lp_add_home(const char *pszHomename, int iDefaultService, 
2649                  const char *user, const char *pszHomedir)
2650 {
2651         int i;
2652         pstring newHomedir;
2653
2654         i = add_a_service(ServicePtrs[iDefaultService], pszHomename);
2655
2656         if (i < 0)
2657                 return (False);
2658
2659         if (!(*(ServicePtrs[iDefaultService]->szPath))
2660             || strequal(ServicePtrs[iDefaultService]->szPath, lp_pathname(GLOBAL_SECTION_SNUM))) {
2661                 pstrcpy(newHomedir, pszHomedir);
2662                 string_set(&ServicePtrs[i]->szPath, newHomedir);
2663         } 
2664
2665         if (!(*(ServicePtrs[i]->comment))) {
2666                 pstring comment;
2667                 slprintf(comment, sizeof(comment) - 1,
2668                          "Home directory of %s", user);
2669                 string_set(&ServicePtrs[i]->comment, comment);
2670         }
2671
2672         /* set the browseable flag from the global default */
2673
2674         ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
2675
2676         ServicePtrs[i]->autoloaded = True;
2677
2678         DEBUG(3, ("adding home's share [%s] for user '%s' at '%s'\n", pszHomename, 
2679                user, ServicePtrs[i]->szPath ));
2680         
2681         return (True);
2682 }
2683
2684 /***************************************************************************
2685  Add a new service, based on an old one.
2686 ***************************************************************************/
2687
2688 int lp_add_service(const char *pszService, int iDefaultService)
2689 {
2690         if (iDefaultService < 0) {
2691                 return add_a_service(&sDefault, pszService);
2692         }
2693
2694         return (add_a_service(ServicePtrs[iDefaultService], pszService));
2695 }
2696
2697 /***************************************************************************
2698  Add the IPC service.
2699 ***************************************************************************/
2700
2701 static BOOL lp_add_ipc(const char *ipc_name, BOOL guest_ok)
2702 {
2703         pstring comment;
2704         int i = add_a_service(&sDefault, ipc_name);
2705
2706         if (i < 0)
2707                 return (False);
2708
2709         slprintf(comment, sizeof(comment) - 1,
2710                  "IPC Service (%s)", Globals.szServerString);
2711
2712         string_set(&ServicePtrs[i]->szPath, tmpdir());
2713         string_set(&ServicePtrs[i]->szUsername, "");
2714         string_set(&ServicePtrs[i]->comment, comment);
2715         string_set(&ServicePtrs[i]->fstype, "IPC");
2716         ServicePtrs[i]->iMaxConnections = 0;
2717         ServicePtrs[i]->bAvailable = True;
2718         ServicePtrs[i]->bRead_only = True;
2719         ServicePtrs[i]->bGuest_only = False;
2720         ServicePtrs[i]->bGuest_ok = guest_ok;
2721         ServicePtrs[i]->bPrint_ok = False;
2722         ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
2723
2724         DEBUG(3, ("adding IPC service\n"));
2725
2726         return (True);
2727 }
2728
2729 /***************************************************************************
2730  Add a new printer service, with defaults coming from service iFrom.
2731 ***************************************************************************/
2732
2733 BOOL lp_add_printer(const char *pszPrintername, int iDefaultService)
2734 {
2735         const char *comment = "From Printcap";
2736         int i = add_a_service(ServicePtrs[iDefaultService], pszPrintername);
2737
2738         if (i < 0)
2739                 return (False);
2740
2741         /* note that we do NOT default the availability flag to True - */
2742         /* we take it from the default service passed. This allows all */
2743         /* dynamic printers to be disabled by disabling the [printers] */
2744         /* entry (if/when the 'available' keyword is implemented!).    */
2745
2746         /* the printer name is set to the service name. */
2747         string_set(&ServicePtrs[i]->szPrintername, pszPrintername);
2748         string_set(&ServicePtrs[i]->comment, comment);
2749
2750         /* set the browseable flag from the gloabl default */
2751         ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
2752
2753         /* Printers cannot be read_only. */
2754         ServicePtrs[i]->bRead_only = False;
2755         /* No share modes on printer services. */
2756         ServicePtrs[i]->bShareModes = False;
2757         /* No oplocks on printer services. */
2758         ServicePtrs[i]->bOpLocks = False;
2759         /* Printer services must be printable. */
2760         ServicePtrs[i]->bPrint_ok = True;
2761         
2762         DEBUG(3, ("adding printer service %s\n", pszPrintername));
2763
2764         return (True);
2765 }
2766
2767 /***************************************************************************
2768  Map a parameter's string representation to something we can use. 
2769  Returns False if the parameter string is not recognised, else TRUE.
2770 ***************************************************************************/
2771
2772 static int map_parameter(const char *pszParmName)
2773 {
2774         int iIndex;
2775
2776         if (*pszParmName == '-')
2777                 return (-1);
2778
2779         for (iIndex = 0; parm_table[iIndex].label; iIndex++)
2780                 if (strwicmp(parm_table[iIndex].label, pszParmName) == 0)
2781                         return (iIndex);
2782
2783         /* Warn only if it isn't parametric option */
2784         if (strchr(pszParmName, ':') == NULL)
2785                 DEBUG(0, ("Unknown parameter encountered: \"%s\"\n", pszParmName));
2786         /* We do return 'fail' for parametric options as well because they are
2787            stored in different storage
2788          */
2789         return (-1);
2790 }
2791
2792 /***************************************************************************
2793  Show all parameter's name, type, [values,] and flags.
2794 ***************************************************************************/
2795
2796 void show_parameter_list(void)
2797 {
2798         int classIndex, parmIndex, enumIndex, flagIndex;
2799         BOOL hadFlag;
2800         const char *section_names[] = { "local", "global", NULL};
2801         const char *type[] = { "P_BOOL", "P_BOOLREV", "P_CHAR", "P_INTEGER",
2802                 "P_OCTAL", "P_LIST", "P_STRING", "P_USTRING", "P_GSTRING",
2803                 "P_UGSTRING", "P_ENUM", "P_SEP"};
2804         unsigned flags[] = { FLAG_BASIC, FLAG_SHARE, FLAG_PRINT, FLAG_GLOBAL,
2805                 FLAG_WIZARD, FLAG_ADVANCED, FLAG_DEVELOPER, FLAG_DEPRECATED,
2806                 FLAG_HIDE, FLAG_DOS_STRING};
2807         const char *flag_names[] = { "FLAG_BASIC", "FLAG_SHARE", "FLAG_PRINT",
2808                 "FLAG_GLOBAL", "FLAG_WIZARD", "FLAG_ADVANCED", "FLAG_DEVELOPER",
2809                 "FLAG_DEPRECATED", "FLAG_HIDE", "FLAG_DOS_STRING", NULL};
2810
2811         for ( classIndex=0; section_names[classIndex]; classIndex++) {
2812                 printf("[%s]\n", section_names[classIndex]);
2813                 for (parmIndex = 0; parm_table[parmIndex].label; parmIndex++) {
2814                         if (parm_table[parmIndex].p_class == classIndex) {
2815                                 printf("%s=%s", 
2816                                         parm_table[parmIndex].label,
2817                                         type[parm_table[parmIndex].type]);
2818                                 switch (parm_table[parmIndex].type) {
2819                                 case P_ENUM:
2820                                         printf(",");
2821                                         for (enumIndex=0; parm_table[parmIndex].enum_list[enumIndex].name; enumIndex++)
2822                                                 printf("%s%s",
2823                                                         enumIndex ? "|" : "",
2824                                                         parm_table[parmIndex].enum_list[enumIndex].name);
2825                                         break;
2826                                 default:
2827                                         break;
2828                                 }
2829                                 printf(",");
2830                                 hadFlag = False;
2831                                 for ( flagIndex=0; flag_names[flagIndex]; flagIndex++ ) {
2832                                         if (parm_table[parmIndex].flags & flags[flagIndex]) {
2833                                                 printf("%s%s",
2834                                                         hadFlag ? "|" : "",
2835                                                         flag_names[flagIndex]);
2836                                                 hadFlag = True;
2837                                         }
2838                                 }
2839                                 printf("\n");
2840                         }
2841                 }
2842         }
2843 }
2844
2845 /***************************************************************************
2846  Set a boolean variable from the text value stored in the passed string.
2847  Returns True in success, False if the passed string does not correctly 
2848  represent a boolean.
2849 ***************************************************************************/
2850
2851 static BOOL set_boolean(BOOL *pb, const char *pszParmValue)
2852 {
2853         BOOL bRetval;
2854
2855         bRetval = True;
2856         if (strwicmp(pszParmValue, "yes") == 0 ||
2857             strwicmp(pszParmValue, "true") == 0 ||
2858             strwicmp(pszParmValue, "1") == 0)
2859                 *pb = True;
2860         else if (strwicmp(pszParmValue, "no") == 0 ||
2861                     strwicmp(pszParmValue, "False") == 0 ||
2862                     strwicmp(pszParmValue, "0") == 0)
2863                 *pb = False;
2864         else {
2865                 DEBUG(0,
2866                       ("ERROR: Badly formed boolean in configuration file: \"%s\".\n",
2867                        pszParmValue));
2868                 bRetval = False;
2869         }
2870         return (bRetval);
2871 }
2872
2873 /***************************************************************************
2874 Find a service by name. Otherwise works like get_service.
2875 ***************************************************************************/
2876
2877 static int getservicebyname(const char *pszServiceName, service * pserviceDest)
2878 {
2879         int iService = -1;
2880         char *canon_name;
2881
2882         if (ServiceHash != NULL) {
2883                 if ( !(canon_name = canonicalize_servicename( pszServiceName )) )
2884                         return -1;
2885
2886                 iService = tdb_fetch_int32(ServiceHash, canon_name );
2887
2888                 if (LP_SNUM_OK(iService)) {
2889                         if (pserviceDest != NULL) {
2890                                 copy_service(pserviceDest, ServicePtrs[iService], NULL);
2891                         }
2892                 } else {
2893                         iService = -1;
2894                 }
2895         }
2896
2897         return (iService);
2898 }
2899
2900 /***************************************************************************
2901  Copy a service structure to another.
2902  If pcopymapDest is NULL then copy all fields
2903 ***************************************************************************/
2904
2905 static void copy_service(service * pserviceDest, service * pserviceSource, BOOL *pcopymapDest)
2906 {
2907         int i;
2908         BOOL bcopyall = (pcopymapDest == NULL);
2909         param_opt_struct *data, *pdata, *paramo;
2910         BOOL not_added;
2911
2912         for (i = 0; parm_table[i].label; i++)
2913                 if (parm_table[i].ptr && parm_table[i].p_class == P_LOCAL &&
2914                     (bcopyall || pcopymapDest[i])) {
2915                         void *def_ptr = parm_table[i].ptr;
2916                         void *src_ptr =
2917                                 ((char *)pserviceSource) + PTR_DIFF(def_ptr,
2918                                                                     &sDefault);
2919                         void *dest_ptr =
2920                                 ((char *)pserviceDest) + PTR_DIFF(def_ptr,
2921                                                                   &sDefault);
2922
2923                         switch (parm_table[i].type) {
2924                                 case P_BOOL:
2925                                 case P_BOOLREV:
2926                                         *(BOOL *)dest_ptr = *(BOOL *)src_ptr;
2927                                         break;
2928
2929                                 case P_INTEGER:
2930                                 case P_ENUM:
2931                                 case P_OCTAL:
2932                                         *(int *)dest_ptr = *(int *)src_ptr;
2933                                         break;
2934
2935                                 case P_CHAR:
2936                                         *(char *)dest_ptr = *(char *)src_ptr;
2937                                         break;
2938
2939                                 case P_STRING:
2940                                         string_set((char **)dest_ptr,
2941                                                    *(char **)src_ptr);
2942                                         break;
2943
2944                                 case P_USTRING:
2945                                         string_set((char **)dest_ptr,
2946                                                    *(char **)src_ptr);
2947                                         strupper_m(*(char **)dest_ptr);
2948                                         break;
2949                                 case P_LIST:
2950                                         str_list_free((char ***)dest_ptr);
2951                                         str_list_copy((char ***)dest_ptr, *(const char ***)src_ptr);
2952                                         break;
2953                                 default:
2954                                         break;
2955                         }
2956                 }
2957
2958         if (bcopyall) {
2959                 init_copymap(pserviceDest);
2960                 if (pserviceSource->copymap)
2961                         memcpy((void *)pserviceDest->copymap,
2962                                (void *)pserviceSource->copymap,
2963                                sizeof(BOOL) * NUMPARAMETERS);
2964         }
2965         
2966         data = pserviceSource->param_opt;
2967         while (data) {
2968                 not_added = True;
2969                 pdata = pserviceDest->param_opt;
2970                 /* Traverse destination */
2971                 while (pdata) {
2972                         /* If we already have same option, override it */
2973                         if (strcmp(pdata->key, data->key) == 0) {
2974                                 string_free(&pdata->value);
2975                                 str_list_free(&data->list);
2976                                 pdata->value = SMB_STRDUP(data->value);
2977                                 not_added = False;
2978                                 break;
2979                         }
2980                         pdata = pdata->next;
2981                 }
2982                 if (not_added) {
2983                     paramo = SMB_XMALLOC_P(param_opt_struct);
2984                     paramo->key = SMB_STRDUP(data->key);
2985                     paramo->value = SMB_STRDUP(data->value);
2986                     paramo->list = NULL;
2987                     DLIST_ADD(pserviceDest->param_opt, paramo);
2988                 }
2989                 data = data->next;
2990         }
2991 }
2992
2993 /***************************************************************************
2994 Check a service for consistency. Return False if the service is in any way
2995 incomplete or faulty, else True.
2996 ***************************************************************************/
2997
2998 BOOL service_ok(int iService)
2999 {
3000         BOOL bRetval;
3001
3002         bRetval = True;
3003         if (ServicePtrs[iService]->szService[0] == '\0') {
3004                 DEBUG(0, ("The following message indicates an internal error:\n"));
3005                 DEBUG(0, ("No service name in service entry.\n"));
3006                 bRetval = False;
3007         }
3008
3009         /* The [printers] entry MUST be printable. I'm all for flexibility, but */
3010         /* I can't see why you'd want a non-printable printer service...        */
3011         if (strwicmp(ServicePtrs[iService]->szService, PRINTERS_NAME) == 0) {
3012                 if (!ServicePtrs[iService]->bPrint_ok) {
3013                         DEBUG(0, ("WARNING: [%s] service MUST be printable!\n",
3014                                ServicePtrs[iService]->szService));
3015                         ServicePtrs[iService]->bPrint_ok = True;
3016                 }
3017                 /* [printers] service must also be non-browsable. */
3018                 if (ServicePtrs[iService]->bBrowseable)
3019                         ServicePtrs[iService]->bBrowseable = False;
3020         }
3021
3022         if (ServicePtrs[iService]->szPath[0] == '\0' &&
3023             strwicmp(ServicePtrs[iService]->szService, HOMES_NAME) != 0 &&
3024             ServicePtrs[iService]->szMSDfsProxy[0] == '\0'
3025             ) {
3026                 DEBUG(0, ("WARNING: No path in service %s - making it unavailable!\n",
3027                         ServicePtrs[iService]->szService));
3028                 ServicePtrs[iService]->bAvailable = False;
3029         }
3030
3031         /* If a service is flagged unavailable, log the fact at level 1. */
3032         if (!ServicePtrs[iService]->bAvailable)
3033                 DEBUG(1, ("NOTE: Service %s is flagged unavailable.\n",
3034                           ServicePtrs[iService]->szService));
3035
3036         return (bRetval);
3037 }
3038
3039 static struct file_lists {
3040         struct file_lists *next;
3041         char *name;
3042         char *subfname;
3043         time_t modtime;
3044 } *file_lists = NULL;
3045
3046 /*******************************************************************
3047  Keep a linked list of all config files so we know when one has changed 
3048  it's date and needs to be reloaded.
3049 ********************************************************************/
3050
3051 static void add_to_file_list(const char *fname, const char *subfname)
3052 {
3053         struct file_lists *f = file_lists;
3054
3055         while (f) {
3056                 if (f->name && !strcmp(f->name, fname))
3057                         break;
3058                 f = f->next;
3059         }
3060
3061         if (!f) {
3062                 f = SMB_MALLOC_P(struct file_lists);
3063                 if (!f)
3064                         return;
3065                 f->next = file_lists;
3066                 f->name = SMB_STRDUP(fname);
3067                 if (!f->name) {
3068                         SAFE_FREE(f);
3069                         return;
3070                 }
3071                 f->subfname = SMB_STRDUP(subfname);
3072                 if (!f->subfname) {
3073                         SAFE_FREE(f);
3074                         return;
3075                 }
3076                 file_lists = f;
3077                 f->modtime = file_modtime(subfname);
3078         } else {
3079                 time_t t = file_modtime(subfname);
3080                 if (t)
3081                         f->modtime = t;
3082         }
3083 }
3084
3085 /*******************************************************************
3086  Check if a config file has changed date.
3087 ********************************************************************/
3088
3089 BOOL lp_file_list_changed(void)
3090 {
3091         struct file_lists *f = file_lists;
3092
3093         DEBUG(6, ("lp_file_list_changed()\n"));
3094
3095         while (f) {
3096                 pstring n2;
3097                 time_t mod_time;
3098
3099                 pstrcpy(n2, f->name);
3100                 standard_sub_basic( get_current_username(),
3101                                     current_user_info.domain,
3102                                     n2, sizeof(n2) );
3103
3104                 DEBUGADD(6, ("file %s -> %s  last mod_time: %s\n",
3105                              f->name, n2, ctime(&f->modtime)));
3106
3107                 mod_time = file_modtime(n2);
3108
3109                 if (mod_time && ((f->modtime != mod_time) || (f->subfname == NULL) || (strcmp(n2, f->subfname) != 0))) {
3110                         DEBUGADD(6,
3111                                  ("file %s modified: %s\n", n2,
3112                                   ctime(&mod_time)));
3113                         f->modtime = mod_time;
3114                         SAFE_FREE(f->subfname);
3115                         f->subfname = SMB_STRDUP(n2);
3116                         return (True);
3117                 }
3118                 f = f->next;
3119         }
3120         return (False);
3121 }
3122
3123 /***************************************************************************
3124  Run standard_sub_basic on netbios name... needed because global_myname
3125  is not accessed through any lp_ macro.
3126  Note: We must *NOT* use string_set() here as ptr points to global_myname.
3127 ***************************************************************************/
3128
3129 static BOOL handle_netbios_name(int snum, const char *pszParmValue, char **ptr)
3130 {
3131         BOOL ret;
3132         pstring netbios_name;
3133
3134         pstrcpy(netbios_name, pszParmValue);
3135
3136         standard_sub_basic(get_current_username(), current_user_info.domain,
3137                            netbios_name, sizeof(netbios_name));
3138
3139         ret = set_global_myname(netbios_name);
3140         string_set(&Globals.szNetbiosName,global_myname());
3141         
3142         DEBUG(4, ("handle_netbios_name: set global_myname to: %s\n",
3143                global_myname()));
3144
3145         return ret;
3146 }
3147
3148 static BOOL handle_charset(int snum, const char *pszParmValue, char **ptr)
3149 {
3150         if (strcmp(*ptr, pszParmValue) != 0) {
3151                 string_set(ptr, pszParmValue);
3152                 init_iconv();
3153         }
3154         return True;
3155 }
3156
3157
3158
3159 static BOOL handle_workgroup(int snum, const char *pszParmValue, char **ptr)
3160 {
3161         BOOL ret;
3162         
3163         ret = set_global_myworkgroup(pszParmValue);
3164         string_set(&Globals.szWorkgroup,lp_workgroup());
3165         
3166         return ret;
3167 }
3168
3169 static BOOL handle_netbios_scope(int snum, const char *pszParmValue, char **ptr)
3170 {
3171         BOOL ret;
3172         
3173         ret = set_global_scope(pszParmValue);
3174         string_set(&Globals.szNetbiosScope,global_scope());
3175
3176         return ret;
3177 }
3178
3179 static BOOL handle_netbios_aliases(int snum, const char *pszParmValue, char **ptr)
3180 {
3181         str_list_free(&Globals.szNetbiosAliases);
3182         Globals.szNetbiosAliases = str_list_make(pszParmValue, NULL);
3183         return set_netbios_aliases((const char **)Globals.szNetbiosAliases);
3184 }
3185
3186 /***************************************************************************
3187  Handle the include operation.
3188 ***************************************************************************/
3189
3190 static BOOL handle_include(int snum, const char *pszParmValue, char **ptr)
3191 {
3192         pstring fname;
3193         pstrcpy(fname, pszParmValue);
3194
3195         standard_sub_basic(get_current_username(), current_user_info.domain,
3196                            fname,sizeof(fname));
3197
3198         add_to_file_list(pszParmValue, fname);
3199
3200         string_set(ptr, fname);
3201
3202         if (file_exist(fname, NULL))
3203                 return (pm_process(fname, do_section, do_parameter));
3204
3205         DEBUG(2, ("Can't find include file %s\n", fname));
3206
3207         return (False);
3208 }
3209
3210 /***************************************************************************
3211  Handle the interpretation of the copy parameter.
3212 ***************************************************************************/
3213
3214 static BOOL handle_copy(int snum, const char *pszParmValue, char **ptr)
3215 {
3216         BOOL bRetval;
3217         int iTemp;
3218         service serviceTemp;
3219
3220         string_set(ptr, pszParmValue);
3221
3222         init_service(&serviceTemp);
3223
3224         bRetval = False;
3225
3226         DEBUG(3, ("Copying service from service %s\n", pszParmValue));
3227
3228         if ((iTemp = getservicebyname(pszParmValue, &serviceTemp)) >= 0) {
3229                 if (iTemp == iServiceIndex) {
3230                         DEBUG(0, ("Can't copy service %s - unable to copy self!\n", pszParmValue));
3231                 } else {
3232                         copy_service(ServicePtrs[iServiceIndex],
3233                                      &serviceTemp,
3234                                      ServicePtrs[iServiceIndex]->copymap);
3235                         bRetval = True;
3236                 }
3237         } else {
3238                 DEBUG(0, ("Unable to copy service - source not found: %s\n", pszParmValue));
3239                 bRetval = False;
3240         }
3241
3242         free_service(&serviceTemp);
3243         return (bRetval);
3244 }
3245
3246 /***************************************************************************
3247  Handle idmap/non unix account uid and gid allocation parameters.  The format of these
3248  parameters is:
3249
3250  [global]
3251
3252         idmap uid = 1000-1999
3253         idmap gid = 700-899
3254
3255  We only do simple parsing checks here.  The strings are parsed into useful
3256  structures in the idmap daemon code.
3257
3258 ***************************************************************************/
3259
3260 /* Some lp_ routines to return idmap [ug]id information */
3261
3262 static uid_t idmap_uid_low, idmap_uid_high;
3263 static gid_t idmap_gid_low, idmap_gid_high;
3264
3265 BOOL lp_idmap_uid(uid_t *low, uid_t *high)
3266 {
3267         if (idmap_uid_low == 0 || idmap_uid_high == 0)
3268                 return False;
3269
3270         if (low)
3271                 *low = idmap_uid_low;
3272
3273         if (high)
3274                 *high = idmap_uid_high;
3275
3276         return True;
3277 }
3278
3279 BOOL lp_idmap_gid(gid_t *low, gid_t *high)
3280 {
3281         if (idmap_gid_low == 0 || idmap_gid_high == 0)
3282                 return False;
3283
3284         if (low)
3285                 *low = idmap_gid_low;
3286
3287         if (high)
3288                 *high = idmap_gid_high;
3289
3290         return True;
3291 }
3292
3293 /* Do some simple checks on "idmap [ug]id" parameter values */
3294
3295 static BOOL handle_idmap_uid(int snum, const char *pszParmValue, char **ptr)
3296 {
3297         uint32 low, high;
3298
3299         if (sscanf(pszParmValue, "%u - %u", &low, &high) != 2 || high < low)
3300                 return False;
3301
3302         /* Parse OK */
3303
3304         string_set(ptr, pszParmValue);
3305
3306         idmap_uid_low = low;
3307         idmap_uid_high = high;
3308
3309         return True;
3310 }
3311
3312 static BOOL handle_idmap_gid(int snum, const char *pszParmValue, char **ptr)
3313 {
3314         uint32 low, high;
3315
3316         if (sscanf(pszParmValue, "%u - %u", &low, &high) != 2 || high < low)
3317                 return False;
3318
3319         /* Parse OK */
3320
3321         string_set(ptr, pszParmValue);
3322
3323         idmap_gid_low = low;
3324         idmap_gid_high = high;
3325
3326         return True;
3327 }
3328
3329 /***************************************************************************
3330  Handle the DEBUG level list.
3331 ***************************************************************************/
3332
3333 static BOOL handle_debug_list( int snum, const char *pszParmValueIn, char **ptr )
3334 {
3335         pstring pszParmValue;
3336
3337         pstrcpy(pszParmValue, pszParmValueIn);
3338         string_set(ptr, pszParmValueIn);
3339         return debug_parse_levels( pszParmValue );
3340 }
3341
3342 /***************************************************************************
3343  Handle ldap suffixes - default to ldapsuffix if sub-suffixes are not defined.
3344 ***************************************************************************/
3345
3346 static const char *append_ldap_suffix( const char *str )
3347 {
3348         const char *suffix_string;
3349
3350
3351         if (!lp_talloc)
3352                 lp_talloc = talloc_init("lp_talloc");
3353
3354         suffix_string = talloc_asprintf( lp_talloc, "%s,%s", str, Globals.szLdapSuffix );
3355         if ( !suffix_string ) {
3356                 DEBUG(0,("append_ldap_suffix: talloc_asprintf() failed!\n"));
3357                 return "";
3358         }
3359
3360         return suffix_string;
3361 }
3362
3363 const char *lp_ldap_machine_suffix(void)
3364 {
3365         if (Globals.szLdapMachineSuffix[0])
3366                 return append_ldap_suffix(Globals.szLdapMachineSuffix);
3367
3368         return lp_string(Globals.szLdapSuffix);
3369 }
3370
3371 const char *lp_ldap_user_suffix(void)
3372 {
3373         if (Globals.szLdapUserSuffix[0])
3374                 return append_ldap_suffix(Globals.szLdapUserSuffix);
3375
3376         return lp_string(Globals.szLdapSuffix);
3377 }
3378
3379 const char *lp_ldap_group_suffix(void)
3380 {
3381         if (Globals.szLdapGroupSuffix[0])
3382                 return append_ldap_suffix(Globals.szLdapGroupSuffix);
3383
3384         return lp_string(Globals.szLdapSuffix);
3385 }
3386
3387 const char *lp_ldap_idmap_suffix(void)
3388 {
3389         if (Globals.szLdapIdmapSuffix[0])
3390                 return append_ldap_suffix(Globals.szLdapIdmapSuffix);
3391
3392         return lp_string(Globals.szLdapSuffix);
3393 }
3394
3395 /****************************************************************************
3396  set the value for a P_ENUM
3397  ***************************************************************************/
3398
3399 static void lp_set_enum_parm( struct parm_struct *parm, const char *pszParmValue,
3400                               int *ptr )
3401 {
3402         int i;
3403
3404         for (i = 0; parm->enum_list[i].name; i++) {
3405                 if ( strequal(pszParmValue, parm->enum_list[i].name)) {
3406                         *ptr = parm->enum_list[i].value;
3407                         break;
3408                 }
3409         }
3410 }
3411
3412 /***************************************************************************
3413 ***************************************************************************/
3414
3415 static BOOL handle_printing(int snum, const char *pszParmValue, char **ptr)
3416 {
3417         static int parm_num = -1;
3418         service *s;
3419
3420         if ( parm_num == -1 )
3421                 parm_num = map_parameter( "printing" );
3422
3423         lp_set_enum_parm( &parm_table[parm_num], pszParmValue, (int*)ptr );
3424
3425         if ( snum < 0 )
3426                 s = &sDefault;
3427         else
3428                 s = ServicePtrs[snum];
3429
3430         init_printer_values( s );
3431
3432         return True;
3433 }
3434
3435
3436 /***************************************************************************
3437  Initialise a copymap.
3438 ***************************************************************************/
3439
3440 static void init_copymap(service * pservice)
3441 {
3442         int i;
3443         SAFE_FREE(pservice->copymap);
3444         pservice->copymap = SMB_MALLOC_ARRAY(BOOL,NUMPARAMETERS);
3445         if (!pservice->copymap)
3446                 DEBUG(0,
3447                       ("Couldn't allocate copymap!! (size %d)\n",
3448                        (int)NUMPARAMETERS));
3449         else
3450                 for (i = 0; i < NUMPARAMETERS; i++)
3451                         pservice->copymap[i] = True;
3452 }
3453
3454 /***************************************************************************
3455  Return the local pointer to a parameter given the service number and the 
3456  pointer into the default structure.
3457 ***************************************************************************/
3458
3459 void *lp_local_ptr(int snum, void *ptr)
3460 {
3461         return (void *)(((char *)ServicePtrs[snum]) + PTR_DIFF(ptr, &sDefault));
3462 }
3463
3464 /***************************************************************************
3465  Process a parameter for a particular service number. If snum < 0
3466  then assume we are in the globals.
3467 ***************************************************************************/
3468
3469 BOOL lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue)
3470 {
3471         int parmnum, i, slen;
3472         void *parm_ptr = NULL;  /* where we are going to store the result */
3473         void *def_ptr = NULL;
3474         pstring param_key;
3475         char *sep;
3476         param_opt_struct *paramo, *data;
3477         BOOL not_added;
3478
3479         parmnum = map_parameter(pszParmName);
3480
3481         if (parmnum < 0) {
3482                 if ((sep=strchr(pszParmName, ':')) != NULL) {
3483                         *sep = '\0';
3484                         ZERO_STRUCT(param_key);
3485                         pstr_sprintf(param_key, "%s:", pszParmName);
3486                         slen = strlen(param_key);
3487                         pstrcat(param_key, sep+1);
3488                         trim_char(param_key+slen, ' ', ' ');
3489                         not_added = True;
3490                         data = (snum < 0) ? Globals.param_opt : 
3491                                 ServicePtrs[snum]->param_opt;
3492                         /* Traverse destination */
3493                         while (data) {
3494                                 /* If we already have same option, override it */
3495                                 if (strcmp(data->key, param_key) == 0) {
3496                                         string_free(&data->value);
3497                                         str_list_free(&data->list);
3498                                         data->value = SMB_STRDUP(pszParmValue);
3499                                         not_added = False;
3500                                         break;
3501                                 }
3502                                 data = data->next;
3503                         }
3504                         if (not_added) {
3505                                 paramo = SMB_XMALLOC_P(param_opt_struct);
3506                                 paramo->key = SMB_STRDUP(param_key);
3507                                 paramo->value = SMB_STRDUP(pszParmValue);
3508                                 paramo->list = NULL;
3509                                 if (snum < 0) {
3510                                         DLIST_ADD(Globals.param_opt, paramo);
3511                                 } else {
3512                                         DLIST_ADD(ServicePtrs[snum]->param_opt, paramo);
3513                                 }
3514                         }
3515
3516                         *sep = ':';
3517                         return (True);
3518                 }
3519                 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n", pszParmName));
3520                 return (True);
3521         }
3522
3523         if (parm_table[parmnum].flags & FLAG_DEPRECATED) {
3524                 DEBUG(1, ("WARNING: The \"%s\" option is deprecated\n",
3525                           pszParmName));
3526         }
3527
3528         def_ptr = parm_table[parmnum].ptr;
3529
3530         /* we might point at a service, the default service or a global */
3531         if (snum < 0) {
3532                 parm_ptr = def_ptr;
3533         } else {
3534                 if (parm_table[parmnum].p_class == P_GLOBAL) {
3535                         DEBUG(0,
3536                               ("Global parameter %s found in service section!\n",
3537                                pszParmName));
3538                         return (True);
3539                 }
3540                 parm_ptr =
3541                         ((char *)ServicePtrs[snum]) + PTR_DIFF(def_ptr,
3542                                                             &sDefault);
3543
3544                 if (!ServicePtrs[snum]->copymap)
3545                         init_copymap(ServicePtrs[snum]);
3546
3547                 /* this handles the aliases - set the copymap for other entries with
3548                    the same data pointer */
3549                 for (i = 0; parm_table[i].label; i++)
3550                         if (parm_table[i].ptr == parm_table[parmnum].ptr)
3551                                 ServicePtrs[snum]->copymap[i] = False;
3552         }
3553
3554         /* if it is a special case then go ahead */
3555         if (parm_table[parmnum].special) {
3556                 parm_table[parmnum].special(snum, pszParmValue, (char **)parm_ptr);
3557                 return (True);
3558         }
3559
3560         /* now switch on the type of variable it is */
3561         switch (parm_table[parmnum].type)
3562         {
3563                 case P_BOOL:
3564                         *(BOOL *)parm_ptr = lp_bool(pszParmValue);
3565                         break;
3566
3567                 case P_BOOLREV:
3568                         *(BOOL *)parm_ptr = !lp_bool(pszParmValue);
3569                         break;
3570
3571                 case P_INTEGER:
3572                         *(int *)parm_ptr = lp_int(pszParmValue);
3573                         break;
3574
3575                 case P_CHAR:
3576                         *(char *)parm_ptr = *pszParmValue;
3577                         break;
3578
3579                 case P_OCTAL:
3580                         i = sscanf(pszParmValue, "%o", (int *)parm_ptr);
3581                         if ( i != 1 ) {
3582                             DEBUG ( 0, ("Invalid octal number %s\n", pszParmName ));
3583                         }
3584                         break;
3585
3586                 case P_LIST:
3587                         str_list_free((char ***)parm_ptr);
3588                         *(char ***)parm_ptr = str_list_make(pszParmValue, NULL);
3589                         break;
3590
3591                 case P_STRING:
3592                         string_set((char **)parm_ptr, pszParmValue);
3593                         break;
3594
3595                 case P_USTRING:
3596                         string_set((char **)parm_ptr, pszParmValue);
3597                         strupper_m(*(char **)parm_ptr);
3598                         break;
3599
3600                 case P_GSTRING:
3601                         pstrcpy((char *)parm_ptr, pszParmValue);
3602                         break;
3603
3604                 case P_UGSTRING:
3605                         pstrcpy((char *)parm_ptr, pszParmValue);
3606                         strupper_m((char *)parm_ptr);
3607                         break;
3608
3609                 case P_ENUM:
3610                         lp_set_enum_parm( &parm_table[parmnum], pszParmValue, (int*)parm_ptr );
3611                         break;
3612                 case P_SEP:
3613                         break;
3614         }
3615
3616         return (True);
3617 }
3618
3619 /***************************************************************************
3620  Process a parameter.
3621 ***************************************************************************/
3622
3623 static BOOL do_parameter(const char *pszParmName, const char *pszParmValue)
3624 {
3625         if (!bInGlobalSection && bGlobalOnly)
3626                 return (True);
3627
3628         DEBUGADD(4, ("doing parameter %s = %s\n", pszParmName, pszParmValue));
3629
3630         return (lp_do_parameter(bInGlobalSection ? -2 : iServiceIndex,
3631                                 pszParmName, pszParmValue));
3632 }
3633
3634 /***************************************************************************
3635  Print a parameter of the specified type.
3636 ***************************************************************************/
3637
3638 static void print_parameter(struct parm_struct *p, void *ptr, FILE * f)
3639 {
3640         int i;
3641         switch (p->type)
3642         {
3643                 case P_ENUM:
3644                         for (i = 0; p->enum_list[i].name; i++) {
3645                                 if (*(int *)ptr == p->enum_list[i].value) {
3646                                         fprintf(f, "%s",
3647                                                 p->enum_list[i].name);
3648                                         break;
3649                                 }
3650                         }
3651                         break;
3652
3653                 case P_BOOL:
3654                         fprintf(f, "%s", BOOLSTR(*(BOOL *)ptr));
3655                         break;
3656
3657                 case P_BOOLREV:
3658                         fprintf(f, "%s", BOOLSTR(!*(BOOL *)ptr));
3659                         break;
3660
3661                 case P_INTEGER:
3662                         fprintf(f, "%d", *(int *)ptr);
3663                         break;
3664
3665                 case P_CHAR:
3666                         fprintf(f, "%c", *(char *)ptr);
3667                         break;
3668
3669                 case P_OCTAL:
3670                         fprintf(f, "%s", octal_string(*(int *)ptr));
3671                         break;
3672
3673                 case P_LIST:
3674                         if ((char ***)ptr && *(char ***)ptr) {
3675                                 char **list = *(char ***)ptr;
3676                                 
3677                                 for (; *list; list++) {
3678                                         /* surround strings with whitespace in double quotes */
3679                                         if ( strchr_m( *list, ' ' ) )
3680                                                 fprintf(f, "\"%s\"%s", *list, ((*(list+1))?", ":""));
3681                                         else
3682                                                 fprintf(f, "%s%s", *list, ((*(list+1))?", ":""));
3683                                 }
3684                         }
3685                         break;
3686
3687                 case P_GSTRING:
3688                 case P_UGSTRING:
3689                         if ((char *)ptr) {
3690                                 fprintf(f, "%s", (char *)ptr);
3691                         }
3692                         break;
3693
3694                 case P_STRING:
3695                 case P_USTRING:
3696                         if (*(char **)ptr) {
3697                                 fprintf(f, "%s", *(char **)ptr);
3698                         }
3699                         break;
3700                 case P_SEP:
3701                         break;
3702         }
3703 }
3704
3705 /***************************************************************************
3706  Check if two parameters are equal.
3707 ***************************************************************************/
3708
3709 static BOOL equal_parameter(parm_type type, void *ptr1, void *ptr2)
3710 {
3711         switch (type) {
3712                 case P_BOOL:
3713                 case P_BOOLREV:
3714                         return (*((BOOL *)ptr1) == *((BOOL *)ptr2));
3715
3716                 case P_INTEGER:
3717                 case P_ENUM:
3718                 case P_OCTAL:
3719                         return (*((int *)ptr1) == *((int *)ptr2));
3720
3721                 case P_CHAR:
3722                         return (*((char *)ptr1) == *((char *)ptr2));
3723                 
3724                 case P_LIST:
3725                         return str_list_compare(*(char ***)ptr1, *(char ***)ptr2);
3726
3727                 case P_GSTRING:
3728                 case P_UGSTRING:
3729                 {
3730                         char *p1 = (char *)ptr1, *p2 = (char *)ptr2;
3731                         if (p1 && !*p1)
3732                                 p1 = NULL;
3733                         if (p2 && !*p2)
3734                                 p2 = NULL;
3735                         return (p1 == p2 || strequal(p1, p2));
3736                 }
3737                 case P_STRING:
3738                 case P_USTRING:
3739                 {
3740                         char *p1 = *(char **)ptr1, *p2 = *(char **)ptr2;
3741                         if (p1 && !*p1)
3742                                 p1 = NULL;
3743                         if (p2 && !*p2)
3744                                 p2 = NULL;
3745                         return (p1 == p2 || strequal(p1, p2));
3746                 }
3747                 case P_SEP:
3748                         break;
3749         }
3750         return (False);
3751 }
3752
3753 /***************************************************************************
3754  Initialize any local varients in the sDefault table.
3755 ***************************************************************************/
3756
3757 void init_locals(void)
3758 {
3759         /* None as yet. */
3760 }
3761
3762 /***************************************************************************
3763  Process a new section (service). At this stage all sections are services.
3764  Later we'll have special sections that permit server parameters to be set.
3765  Returns True on success, False on failure. 
3766 ***************************************************************************/
3767
3768 static BOOL do_section(const char *pszSectionName)
3769 {
3770         BOOL bRetval;
3771         BOOL isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
3772                          (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
3773         bRetval = False;
3774
3775         /* if we were in a global section then do the local inits */
3776         if (bInGlobalSection && !isglobal)
3777                 init_locals();
3778
3779         /* if we've just struck a global section, note the fact. */
3780         bInGlobalSection = isglobal;
3781
3782         /* check for multiple global sections */
3783         if (bInGlobalSection) {
3784                 DEBUG(3, ("Processing section \"[%s]\"\n", pszSectionName));
3785                 return (True);
3786         }
3787
3788         if (!bInGlobalSection && bGlobalOnly)
3789                 return (True);
3790
3791         /* if we have a current service, tidy it up before moving on */
3792         bRetval = True;
3793
3794         if (iServiceIndex >= 0)
3795                 bRetval = service_ok(iServiceIndex);
3796
3797         /* if all is still well, move to the next record in the services array */
3798         if (bRetval) {
3799                 /* We put this here to avoid an odd message order if messages are */
3800                 /* issued by the post-processing of a previous section. */
3801                 DEBUG(2, ("Processing section \"[%s]\"\n", pszSectionName));
3802
3803                 if ((iServiceIndex = add_a_service(&sDefault, pszSectionName))
3804                     < 0) {
3805                         DEBUG(0, ("Failed to add a new service\n"));
3806                         return (False);
3807                 }
3808         }
3809
3810         return (bRetval);
3811 }
3812
3813
3814 /***************************************************************************
3815  Determine if a partcular base parameter is currentl set to the default value.
3816 ***************************************************************************/
3817
3818 static BOOL is_default(int i)
3819 {
3820         if (!defaults_saved)
3821                 return False;
3822         switch (parm_table[i].type) {
3823                 case P_LIST:
3824                         return str_list_compare (parm_table[i].def.lvalue, 
3825                                                 *(char ***)parm_table[i].ptr);
3826                 case P_STRING:
3827                 case P_USTRING:
3828                         return strequal(parm_table[i].def.svalue,
3829                                         *(char **)parm_table[i].ptr);
3830                 case P_GSTRING:
3831                 case P_UGSTRING:
3832                         return strequal(parm_table[i].def.svalue,
3833                                         (char *)parm_table[i].ptr);
3834                 case P_BOOL:
3835                 case P_BOOLREV:
3836                         return parm_table[i].def.bvalue ==
3837                                 *(BOOL *)parm_table[i].ptr;
3838                 case P_CHAR:
3839                         return parm_table[i].def.cvalue ==
3840                                 *(char *)parm_table[i].ptr;
3841                 case P_INTEGER:
3842                 case P_OCTAL:
3843                 case P_ENUM:
3844                         return parm_table[i].def.ivalue ==
3845                                 *(int *)parm_table[i].ptr;
3846                 case P_SEP:
3847                         break;
3848         }
3849         return False;
3850 }
3851
3852 /***************************************************************************
3853 Display the contents of the global structure.
3854 ***************************************************************************/
3855
3856 static void dump_globals(FILE *f)
3857 {
3858         int i;
3859         param_opt_struct *data;
3860         
3861         fprintf(f, "[global]\n");
3862
3863         for (i = 0; parm_table[i].label; i++)
3864                 if (parm_table[i].p_class == P_GLOBAL &&
3865                     parm_table[i].ptr &&
3866                     (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) {
3867                         if (defaults_saved && is_default(i))
3868                                 continue;
3869                         fprintf(f, "\t%s = ", parm_table[i].label);
3870                         print_parameter(&parm_table[i], parm_table[i].ptr, f);
3871                         fprintf(f, "\n");
3872         }
3873         if (Globals.param_opt != NULL) {
3874                 data = Globals.param_opt;
3875                 while(data) {
3876                         fprintf(f, "\t%s = %s\n", data->key, data->value);
3877                         data = data->next;
3878                 }
3879         }
3880
3881 }
3882
3883 /***************************************************************************
3884  Return True if a local parameter is currently set to the global default.
3885 ***************************************************************************/
3886
3887 BOOL lp_is_default(int snum, struct parm_struct *parm)
3888 {
3889         int pdiff = PTR_DIFF(parm->ptr, &sDefault);
3890
3891         return equal_parameter(parm->type,
3892                                ((char *)ServicePtrs[snum]) + pdiff,
3893                                ((char *)&sDefault) + pdiff);
3894 }
3895
3896 /***************************************************************************
3897  Display the contents of a single services record.
3898 ***************************************************************************/
3899
3900 static void dump_a_service(service * pService, FILE * f)
3901 {
3902         int i;
3903         param_opt_struct *data;
3904         
3905         if (pService != &sDefault)
3906                 fprintf(f, "[%s]\n", pService->szService);
3907
3908         for (i = 0; parm_table[i].label; i++) {
3909
3910                 if (parm_table[i].p_class == P_LOCAL &&
3911                     parm_table[i].ptr &&
3912                     (*parm_table[i].label != '-') &&
3913                     (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) 
3914                 {
3915                 
3916                         int pdiff = PTR_DIFF(parm_table[i].ptr, &sDefault);
3917
3918                         if (pService == &sDefault) {
3919                                 if (defaults_saved && is_default(i))
3920                                         continue;
3921                         } else {
3922                                 if (equal_parameter(parm_table[i].type,
3923                                                     ((char *)pService) +
3924                                                     pdiff,
3925                                                     ((char *)&sDefault) +
3926                                                     pdiff))
3927                                         continue;
3928                         }
3929
3930                         fprintf(f, "\t%s = ", parm_table[i].label);
3931                         print_parameter(&parm_table[i],
3932                                         ((char *)pService) + pdiff, f);
3933                         fprintf(f, "\n");
3934                 }
3935         }
3936
3937                 if (pService->param_opt != NULL) {
3938                         data = pService->param_opt;
3939                         while(data) {
3940                                 fprintf(f, "\t%s = %s\n", data->key, data->value);
3941                                 data = data->next;
3942                         }
3943                 }
3944 }
3945
3946 /***************************************************************************
3947  Display the contents of a parameter of a single services record.
3948 ***************************************************************************/
3949
3950 BOOL dump_a_parameter(int snum, char *parm_name, FILE * f, BOOL isGlobal)
3951 {
3952         int i;
3953         BOOL result = False;
3954         parm_class p_class;
3955         unsigned flag = 0;
3956         fstring local_parm_name;
3957         char *parm_opt;
3958         const char *parm_opt_value;
3959
3960         /* check for parametrical option */
3961         fstrcpy( local_parm_name, parm_name);
3962         parm_opt = strchr( local_parm_name, ':');
3963
3964         if (parm_opt) {
3965                 *parm_opt = '\0';
3966                 parm_opt++;
3967                 if (strlen(parm_opt)) {
3968                         parm_opt_value = lp_parm_const_string( snum,
3969                                 local_parm_name, parm_opt, NULL);
3970                         if (parm_opt_value) {
3971                                 printf( "%s\n", parm_opt_value);
3972                                 result = True;
3973                         }
3974                 }
3975                 return result;
3976         }
3977
3978         /* check for a key and print the value */
3979         if (isGlobal) {
3980                 p_class = P_GLOBAL;
3981                 flag = FLAG_GLOBAL;
3982         } else
3983                 p_class = P_LOCAL;
3984
3985         for (i = 0; parm_table[i].label; i++) {
3986                 if (strwicmp(parm_table[i].label, parm_name) == 0 &&
3987                     (parm_table[i].p_class == p_class || parm_table[i].flags & flag) &&
3988                     parm_table[i].ptr &&
3989                     (*parm_table[i].label != '-') &&
3990                     (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) 
3991                 {
3992                         void *ptr;
3993
3994                         if (isGlobal) {
3995                                 ptr = parm_table[i].ptr;
3996                         } else {
3997                                 service * pService = ServicePtrs[snum];
3998                                 ptr = ((char *)pService) +
3999                                         PTR_DIFF(parm_table[i].ptr, &sDefault);
4000                         }
4001
4002                         print_parameter(&parm_table[i],
4003                                         ptr, f);
4004                         fprintf(f, "\n");
4005                         result = True;
4006                         break;
4007                 }
4008         }
4009
4010         return result;
4011 }
4012
4013 /***************************************************************************
4014  Return info about the next parameter in a service.
4015  snum==GLOBAL_SECTION_SNUM gives the globals.
4016  Return NULL when out of parameters.
4017 ***************************************************************************/
4018
4019 struct parm_struct *lp_next_parameter(int snum, int *i, int allparameters)
4020 {
4021         if (snum < 0) {
4022                 /* do the globals */
4023                 for (; parm_table[*i].label; (*i)++) {
4024                         if (parm_table[*i].p_class == P_SEPARATOR)
4025                                 return &parm_table[(*i)++];
4026
4027                         if (!parm_table[*i].ptr
4028                             || (*parm_table[*i].label == '-'))
4029                                 continue;
4030
4031                         if ((*i) > 0
4032                             && (parm_table[*i].ptr ==
4033                                 parm_table[(*i) - 1].ptr))
4034                                 continue;
4035
4036                         return &parm_table[(*i)++];
4037                 }
4038         } else {
4039                 service *pService = ServicePtrs[snum];
4040
4041                 for (; parm_table[*i].label; (*i)++) {
4042                         if (parm_table[*i].p_class == P_SEPARATOR)
4043                                 return &parm_table[(*i)++];
4044
4045                         if (parm_table[*i].p_class == P_LOCAL &&
4046                             parm_table[*i].ptr &&
4047                             (*parm_table[*i].label != '-') &&
4048                             ((*i) == 0 ||
4049                              (parm_table[*i].ptr !=
4050                               parm_table[(*i) - 1].ptr)))
4051                         {
4052                                 int pdiff =
4053                                         PTR_DIFF(parm_table[*i].ptr,
4054                                                  &sDefault);
4055
4056                                 if (allparameters ||
4057                                     !equal_parameter(parm_table[*i].type,
4058                                                      ((char *)pService) +
4059                                                      pdiff,
4060                                                      ((char *)&sDefault) +
4061                                                      pdiff))
4062                                 {
4063                                         return &parm_table[(*i)++];
4064                                 }
4065                         }
4066                 }
4067         }
4068
4069         return NULL;
4070 }
4071
4072
4073 #if 0
4074 /***************************************************************************
4075  Display the contents of a single copy structure.
4076 ***************************************************************************/
4077 static void dump_copy_map(BOOL *pcopymap)
4078 {
4079         int i;
4080         if (!pcopymap)
4081                 return;
4082
4083         printf("\n\tNon-Copied parameters:\n");
4084
4085         for (i = 0; parm_table[i].label; i++)
4086                 if (parm_table[i].p_class == P_LOCAL &&
4087                     parm_table[i].ptr && !pcopymap[i] &&
4088                     (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr)))
4089                 {
4090                         printf("\t\t%s\n", parm_table[i].label);
4091                 }
4092 }
4093 #endif
4094
4095 /***************************************************************************
4096  Return TRUE if the passed service number is within range.
4097 ***************************************************************************/
4098
4099 BOOL lp_snum_ok(int iService)
4100 {
4101         return (LP_SNUM_OK(iService) && ServicePtrs[iService]->bAvailable);
4102 }
4103
4104 /***************************************************************************
4105  Auto-load some home services.
4106 ***************************************************************************/
4107
4108 static void lp_add_auto_services(char *str)
4109 {
4110         char *s;
4111         char *p;
4112         int homes;
4113
4114         if (!str)
4115                 return;
4116
4117         s = SMB_STRDUP(str);
4118         if (!s)
4119                 return;
4120
4121         homes = lp_servicenumber(HOMES_NAME);
4122
4123         for (p = strtok(s, LIST_SEP); p; p = strtok(NULL, LIST_SEP)) {
4124                 char *home = get_user_home_dir(p);
4125
4126                 if (lp_servicenumber(p) >= 0)
4127                         continue;
4128
4129                 if (home && homes >= 0)
4130                         lp_add_home(p, homes, p, home);
4131         }
4132         SAFE_FREE(s);
4133 }
4134
4135 /***************************************************************************
4136  Auto-load one printer.
4137 ***************************************************************************/
4138
4139 void lp_add_one_printer(char *name, char *comment)
4140 {
4141         int printers = lp_servicenumber(PRINTERS_NAME);
4142         int i;
4143
4144         if (lp_servicenumber(name) < 0) {
4145                 lp_add_printer(name, printers);
4146                 if ((i = lp_servicenumber(name)) >= 0) {
4147                         string_set(&ServicePtrs[i]->comment, comment);
4148                         ServicePtrs[i]->autoloaded = True;
4149                 }
4150         }
4151 }
4152
4153 /***************************************************************************
4154  Have we loaded a services file yet?
4155 ***************************************************************************/
4156
4157 BOOL lp_loaded(void)
4158 {
4159         return (bLoaded);
4160 }
4161
4162 /***************************************************************************
4163  Unload unused services.
4164 ***************************************************************************/
4165
4166 void lp_killunused(BOOL (*snumused) (int))
4167 {
4168         int i;
4169         for (i = 0; i < iNumServices; i++) {
4170                 if (!VALID(i))
4171                         continue;
4172
4173                 /* don't kill autoloaded or usershare services */
4174                 if ( ServicePtrs[i]->autoloaded ||
4175                                 ServicePtrs[i]->usershare == USERSHARE_VALID) {
4176                         continue;
4177                 }
4178
4179                 if (!snumused || !snumused(i)) {
4180                         free_service_byindex(i);
4181                 }
4182         }
4183 }
4184
4185 /***************************************************************************
4186  Unload a service.
4187 ***************************************************************************/
4188
4189 void lp_killservice(int iServiceIn)
4190 {
4191         if (VALID(iServiceIn)) {
4192                 free_service_byindex(iServiceIn);
4193         }
4194 }
4195
4196 /***************************************************************************
4197  Save the curent values of all global and sDefault parameters into the 
4198  defaults union. This allows swat and testparm to show only the
4199  changed (ie. non-default) parameters.
4200 ***************************************************************************/
4201
4202 static void lp_save_defaults(void)
4203 {
4204         int i;
4205         for (i = 0; parm_table[i].label; i++) {
4206                 if (i > 0 && parm_table[i].ptr == parm_table[i - 1].ptr)
4207                         continue;
4208                 switch (parm_table[i].type) {
4209                         case P_LIST:
4210                                 str_list_copy(&(parm_table[i].def.lvalue),
4211                                             *(const char ***)parm_table[i].ptr);
4212                                 break;
4213                         case P_STRING:
4214                         case P_USTRING:
4215                                 if (parm_table[i].ptr) {
4216                                         parm_table[i].def.svalue = SMB_STRDUP(*(char **)parm_table[i].ptr);
4217                                 } else {
4218                                         parm_table[i].def.svalue = NULL;
4219                                 }
4220                                 break;
4221                         case P_GSTRING:
4222                         case P_UGSTRING:
4223                                 if (parm_table[i].ptr) {
4224                                         parm_table[i].def.svalue = SMB_STRDUP((char *)parm_table[i].ptr);
4225                                 } else {
4226                                         parm_table[i].def.svalue = NULL;
4227                                 }
4228                                 break;
4229                         case P_BOOL:
4230                         case P_BOOLREV:
4231                                 parm_table[i].def.bvalue =
4232                                         *(BOOL *)parm_table[i].ptr;
4233                                 break;
4234                         case P_CHAR:
4235                                 parm_table[i].def.cvalue =
4236                                         *(char *)parm_table[i].ptr;
4237                                 break;
4238                         case P_INTEGER:
4239                         case P_OCTAL:
4240                         case P_ENUM:
4241                                 parm_table[i].def.ivalue =
4242                                         *(int *)parm_table[i].ptr;
4243                                 break;
4244                         case P_SEP:
4245                                 break;
4246                 }
4247         }
4248         defaults_saved = True;
4249 }
4250
4251 /*******************************************************************
4252  Set the server type we will announce as via nmbd.
4253 ********************************************************************/
4254
4255 static const struct srv_role_tab {
4256         uint32 role;
4257         const char *role_str;
4258 } srv_role_tab [] = {
4259         { ROLE_STANDALONE, "ROLE_STANDALONE" },
4260         { ROLE_DOMAIN_MEMBER, "ROLE_DOMAIN_MEMBER" },
4261         { ROLE_DOMAIN_BDC, "ROLE_DOMAIN_BDC" },
4262         { ROLE_DOMAIN_PDC, "ROLE_DOMAIN_PDC" },
4263         { 0, NULL }
4264 };
4265
4266 const char* server_role_str(uint32 role)
4267 {
4268         int i = 0;
4269         for (i=0; srv_role_tab[i].role_str; i++) {
4270                 if (role == srv_role_tab[i].role) {
4271                         return srv_role_tab[i].role_str;
4272                 }
4273         }
4274         return NULL;
4275 }
4276
4277 static void set_server_role(void)
4278 {
4279         server_role = ROLE_STANDALONE;
4280
4281         switch (lp_security()) {
4282                 case SEC_SHARE:
4283                         if (lp_domain_logons())
4284                                 DEBUG(0, ("Server's Role (logon server) conflicts with share-level security\n"));
4285                         break;
4286                 case SEC_SERVER:
4287                         if (lp_domain_logons())
4288                                 DEBUG(0, ("Server's Role (logon server) conflicts with server-level security\n"));
4289                         /* this used to be considered ROLE_DOMAIN_MEMBER but that's just wrong */
4290                         server_role = ROLE_STANDALONE;
4291                         break;
4292                 case SEC_DOMAIN:
4293                         if (lp_domain_logons()) {
4294                                 DEBUG(1, ("Server's Role (logon server) NOT ADVISED with domain-level security\n"));
4295                                 server_role = ROLE_DOMAIN_BDC;
4296                                 break;
4297                         }
4298                         server_role = ROLE_DOMAIN_MEMBER;
4299                         break;
4300                 case SEC_ADS:
4301                         if (lp_domain_logons()) {
4302                                 server_role = ROLE_DOMAIN_PDC;
4303                                 break;
4304                         }
4305                         server_role = ROLE_DOMAIN_MEMBER;
4306                         break;
4307                 case SEC_USER:
4308                         if (lp_domain_logons()) {
4309
4310                                 if (Globals.bDomainMaster) /* auto or yes */ 
4311                                         server_role = ROLE_DOMAIN_PDC;
4312                                 else
4313                                         server_role = ROLE_DOMAIN_BDC;
4314                         }
4315                         break;
4316                 default:
4317                         DEBUG(0, ("Server's Role undefined due to unknown security mode\n"));
4318                         break;
4319         }
4320
4321         DEBUG(10, ("set_server_role: role = %s\n", server_role_str(server_role)));
4322 }
4323
4324 /***********************************************************
4325  If we should send plaintext/LANMAN passwords in the clinet
4326 ************************************************************/
4327
4328 static void set_allowed_client_auth(void)
4329 {
4330         if (Globals.bClientNTLMv2Auth) {
4331                 Globals.bClientLanManAuth = False;
4332         }
4333         if (!Globals.bClientLanManAuth) {
4334                 Globals.bClientPlaintextAuth = False;
4335         }
4336 }
4337
4338 /***************************************************************************
4339  JRA.
4340  The following code allows smbd to read a user defined share file.
4341  Yes, this is my intent. Yes, I'm comfortable with that...
4342
4343  THE FOLLOWING IS SECURITY CRITICAL CODE.
4344
4345  It washes your clothes, it cleans your house, it guards you while you sleep...
4346  Do not f%^k with it....
4347 ***************************************************************************/
4348
4349 #define MAX_USERSHARE_FILE_SIZE (10*1024)
4350
4351 /***************************************************************************
4352  Check allowed stat state of a usershare file.
4353  Ensure we print out who is dicking with us so the admin can
4354  get their sorry ass fired.
4355 ***************************************************************************/
4356
4357 static BOOL check_usershare_stat(const char *fname, SMB_STRUCT_STAT *psbuf)
4358 {
4359         if (!S_ISREG(psbuf->st_mode)) {
4360                 DEBUG(0,("check_usershare_stat: file %s owned by uid %u is "
4361                         "not a regular file\n",
4362                         fname, (unsigned int)psbuf->st_uid ));
4363                 return False;
4364         }
4365
4366         /* Ensure this doesn't have the other write bit set. */
4367         if (psbuf->st_mode & S_IWOTH) {
4368                 DEBUG(0,("check_usershare_stat: file %s owned by uid %u allows "
4369                         "public write. Refusing to allow as a usershare file.\n",
4370                         fname, (unsigned int)psbuf->st_uid ));
4371                 return False;
4372         }
4373
4374         /* Should be 10k or less. */
4375         if (psbuf->st_size > MAX_USERSHARE_FILE_SIZE) {
4376                 DEBUG(0,("check_usershare_stat: file %s owned by uid %u is "
4377                         "too large (%u) to be a user share file.\n",
4378                         fname, (unsigned int)psbuf->st_uid,
4379                         (unsigned int)psbuf->st_size ));
4380                 return False;
4381         }
4382
4383         return True;
4384 }
4385
4386 /***************************************************************************
4387  Parse the contents of a usershare file.
4388 ***************************************************************************/
4389
4390 enum usershare_err parse_usershare_file(TALLOC_CTX *ctx, 
4391                         SMB_STRUCT_STAT *psbuf,
4392                         const char *servicename,
4393                         int snum,
4394                         char **lines,
4395                         int numlines,
4396                         pstring sharepath,
4397                         pstring comment,
4398                         SEC_DESC **ppsd,
4399                         BOOL *pallow_guest)
4400 {
4401         const char **prefixallowlist = lp_usershare_prefix_allow_list();
4402         const char **prefixdenylist = lp_usershare_prefix_deny_list();
4403         int us_vers;
4404         SMB_STRUCT_DIR *dp;
4405         SMB_STRUCT_STAT sbuf;
4406
4407         *pallow_guest = False;
4408
4409         if (numlines < 4) {
4410                 return USERSHARE_MALFORMED_FILE;
4411         }
4412
4413         if (strcmp(lines[0], "#VERSION 1") == 0) {
4414                 us_vers = 1;
4415         } else if (strcmp(lines[0], "#VERSION 2") == 0) {
4416                 us_vers = 2;
4417                 if (numlines < 5) {
4418                         return USERSHARE_MALFORMED_FILE;
4419                 }
4420         } else {
4421                 return USERSHARE_BAD_VERSION;
4422         }
4423
4424         if (strncmp(lines[1], "path=", 5) != 0) {
4425                 return USERSHARE_MALFORMED_PATH;
4426         }
4427
4428         pstrcpy(sharepath, &lines[1][5]);
4429         trim_string(sharepath, " ", " ");
4430
4431         if (strncmp(lines[2], "comment=", 8) != 0) {
4432                 return USERSHARE_MALFORMED_COMMENT_DEF;
4433         }
4434
4435         pstrcpy(comment, &lines[2][8]);
4436         trim_string(comment, " ", " ");
4437         trim_char(comment, '"', '"');
4438
4439         if (strncmp(lines[3], "usershare_acl=", 14) != 0) {
4440                 return USERSHARE_MALFORMED_ACL_DEF;
4441         }
4442
4443         if (!parse_usershare_acl(ctx, &lines[3][14], ppsd)) {
4444                 return USERSHARE_ACL_ERR;
4445         }
4446
4447         if (us_vers == 2) {
4448                 if (strncmp(lines[4], "guest_ok=", 9) != 0) {
4449                         return USERSHARE_MALFORMED_ACL_DEF;
4450                 }
4451                 if (lines[4][9] == 'y') {
4452                         *pallow_guest = True;
4453                 }
4454         }
4455
4456         if (snum != -1 && (strcmp(sharepath, ServicePtrs[snum]->szPath) == 0)) {
4457                 /* Path didn't change, no checks needed. */
4458                 return USERSHARE_OK;
4459         }
4460
4461         /* The path *must* be absolute. */
4462         if (sharepath[0] != '/') {
4463                 DEBUG(2,("parse_usershare_file: share %s: path %s is not an absolute path.\n",
4464                         servicename, sharepath));
4465                 return USERSHARE_PATH_NOT_ABSOLUTE;
4466         }
4467
4468         /* If there is a usershare prefix deny list ensure one of these paths
4469            doesn't match the start of the user given path. */
4470         if (prefixdenylist) {
4471                 int i;
4472                 for ( i=0; prefixdenylist[i]; i++ ) {
4473                         DEBUG(10,("parse_usershare_file: share %s : checking prefixdenylist[%d]='%s' against %s\n",
4474                                 servicename, i, prefixdenylist[i], sharepath ));
4475                         if (memcmp( sharepath, prefixdenylist[i], strlen(prefixdenylist[i])) == 0) {
4476                                 DEBUG(2,("parse_usershare_file: share %s path %s starts with one of the "
4477                                         "usershare prefix deny list entries.\n",
4478                                         servicename, sharepath));
4479                                 return USERSHARE_PATH_IS_DENIED;
4480                         }
4481                 }
4482         }
4483
4484         /* If there is a usershare prefix allow list ensure one of these paths
4485            does match the start of the user given path. */
4486
4487         if (prefixallowlist) {
4488                 int i;
4489                 for ( i=0; prefixallowlist[i]; i++ ) {
4490                         DEBUG(10,("parse_usershare_file: share %s checking prefixallowlist[%d]='%s' against %s\n",
4491                                 servicename, i, prefixallowlist[i], sharepath ));
4492                         if (memcmp( sharepath, prefixallowlist[i], strlen(prefixallowlist[i])) == 0) {
4493                                 break;
4494                         }
4495                 }
4496                 if (prefixallowlist[i] == NULL) {
4497                         DEBUG(2,("parse_usershare_file: share %s path %s doesn't start with one of the "
4498                                 "usershare prefix allow list entries.\n",
4499                                 servicename, sharepath));
4500                         return USERSHARE_PATH_NOT_ALLOWED;
4501                 }
4502         }
4503
4504         /* Ensure this is pointing to a directory. */
4505         dp = sys_opendir(sharepath);
4506
4507         if (!dp) {
4508                 DEBUG(2,("parse_usershare_file: share %s path %s is not a directory.\n",
4509                         servicename, sharepath));
4510                 return USERSHARE_PATH_NOT_DIRECTORY;
4511         }
4512
4513         /* Ensure the owner of the usershare file has permission to share
4514            this directory. */
4515
4516         if (sys_stat(sharepath, &sbuf) == -1) {
4517                 DEBUG(2,("parse_usershare_file: share %s : stat failed on path %s. %s\n",
4518                         servicename, sharepath, strerror(errno) ));
4519                 sys_closedir(dp);
4520                 return USERSHARE_POSIX_ERR;
4521         }
4522
4523         sys_closedir(dp);
4524
4525         if (!S_ISDIR(sbuf.st_mode)) {
4526                 DEBUG(2,("parse_usershare_file: share %s path %s is not a directory.\n",
4527                         servicename, sharepath ));
4528                 return USERSHARE_PATH_NOT_DIRECTORY;
4529         }
4530
4531         /* Check if sharing is restricted to owner-only. */
4532         /* psbuf is the stat of the usershare definition file,
4533            sbuf is the stat of the target directory to be shared. */
4534
4535         if (lp_usershare_owner_only()) {
4536                 /* root can share anything. */
4537                 if ((psbuf->st_uid != 0) && (sbuf.st_uid != psbuf->st_uid)) {
4538                         return USERSHARE_PATH_NOT_ALLOWED;
4539                 }
4540         }
4541
4542         return USERSHARE_OK;
4543 }
4544
4545 /***************************************************************************
4546  Deal with a usershare file.
4547  Returns:
4548         >= 0 - snum
4549         -1 - Bad name, invalid contents.
4550            - service name already existed and not a usershare, problem
4551             with permissions to share directory etc.
4552 ***************************************************************************/
4553
4554 static int process_usershare_file(const char *dir_name, const char *file_name, int snum_template)
4555 {
4556         SMB_STRUCT_STAT sbuf;
4557         SMB_STRUCT_STAT lsbuf;
4558         pstring fname;
4559         pstring sharepath;
4560         pstring comment;
4561         fstring service_name;
4562         char **lines = NULL;
4563         int numlines = 0;
4564         int fd = -1;
4565         int iService = -1;
4566         TALLOC_CTX *ctx = NULL;
4567         SEC_DESC *psd = NULL;
4568         BOOL guest_ok = False;
4569
4570         /* Ensure share name doesn't contain invalid characters. */
4571         if (!validate_net_name(file_name, INVALID_SHARENAME_CHARS, strlen(file_name))) {
4572                 DEBUG(0,("process_usershare_file: share name %s contains "
4573                         "invalid characters (any of %s)\n",
4574                         file_name, INVALID_SHARENAME_CHARS ));
4575                 return -1;
4576         }
4577
4578         fstrcpy(service_name, file_name);
4579
4580         pstrcpy(fname, dir_name);
4581         pstrcat(fname, "/");
4582         pstrcat(fname, file_name);
4583
4584         /* Minimize the race condition by doing an lstat before we
4585            open and fstat. Ensure this isn't a symlink link. */
4586
4587         if (sys_lstat(fname, &lsbuf) != 0) {
4588                 DEBUG(0,("process_usershare_file: stat of %s failed. %s\n",
4589                         fname, strerror(errno) ));
4590                 return -1;
4591         }
4592
4593         /* This must be a regular file, not a symlink, directory or
4594            other strange filetype. */
4595         if (!check_usershare_stat(fname, &lsbuf)) {
4596                 return -1;
4597         }
4598
4599         /* See if there is already a servicenum for this name. */
4600         /* tdb_fetch_int32 returns -1 if not found. */
4601         iService = (int)tdb_fetch_int32(ServiceHash, canonicalize_servicename(service_name) );
4602
4603         if (iService != -1 && ServicePtrs[iService]->usershare_last_mod == lsbuf.st_mtime) {
4604                 /* Nothing changed - Mark valid and return. */
4605                 DEBUG(10,("process_usershare_file: service %s not changed.\n",
4606                         service_name ));
4607                 ServicePtrs[iService]->usershare = USERSHARE_VALID;
4608                 return iService;
4609         }
4610
4611         /* Try and open the file read only - no symlinks allowed. */
4612 #ifdef O_NOFOLLOW
4613         fd = sys_open(fname, O_RDONLY|O_NOFOLLOW, 0);
4614 #else
4615         fd = sys_open(fname, O_RDONLY, 0);
4616 #endif
4617
4618         if (fd == -1) {
4619                 DEBUG(0,("process_usershare_file: unable to open %s. %s\n",
4620                         fname, strerror(errno) ));
4621                 return -1;
4622         }
4623
4624         /* Now fstat to be *SURE* it's a regular file. */
4625         if (sys_fstat(fd, &sbuf) != 0) {
4626                 close(fd);
4627                 DEBUG(0,("process_usershare_file: fstat of %s failed. %s\n",
4628                         fname, strerror(errno) ));
4629                 return -1;
4630         }
4631
4632         /* Is it the same dev/inode as was lstated ? */
4633         if (lsbuf.st_dev != sbuf.st_dev || lsbuf.st_ino != sbuf.st_ino) {
4634                 close(fd);
4635                 DEBUG(0,("process_usershare_file: fstat of %s is a different file from lstat. "
4636                         "Symlink spoofing going on ?\n", fname ));
4637                 return -1;
4638         }
4639
4640         /* This must be a regular file, not a symlink, directory or
4641            other strange filetype. */
4642         if (!check_usershare_stat(fname, &sbuf)) {
4643                 return -1;
4644         }
4645
4646         lines = fd_lines_load(fd, &numlines, MAX_USERSHARE_FILE_SIZE);
4647
4648         close(fd);
4649         if (lines == NULL) {
4650                 DEBUG(0,("process_usershare_file: loading file %s owned by %u failed.\n",
4651                         fname, (unsigned int)sbuf.st_uid ));
4652                 return -1;
4653         }
4654
4655         /* Should we allow printers to be shared... ? */
4656         ctx = talloc_init("usershare_sd_xctx");
4657         if (!ctx) {
4658                 file_lines_free(lines);
4659                 return 1;
4660         }
4661
4662         if (parse_usershare_file(ctx, &sbuf, service_name,
4663                         iService, lines, numlines, sharepath,
4664                         comment, &psd, &guest_ok) != USERSHARE_OK) {
4665                 talloc_destroy(ctx);
4666                 file_lines_free(lines);
4667                 return -1;
4668         }
4669
4670         file_lines_free(lines);
4671
4672         /* Everything ok - add the service possibly using a template. */
4673         if (iService < 0) {
4674                 const service *sp = &sDefault;
4675                 if (snum_template != -1) {
4676                         sp = ServicePtrs[snum_template];
4677                 }
4678
4679                 if ((iService = add_a_service(sp, service_name)) < 0) {
4680                         DEBUG(0, ("process_usershare_file: Failed to add "
4681                                 "new service %s\n", service_name));
4682                         talloc_destroy(ctx);
4683                         return -1;
4684                 }
4685
4686                 /* Read only is controlled by usershare ACL below. */
4687                 ServicePtrs[iService]->bRead_only = False;
4688         }
4689
4690         /* Write the ACL of the new/modified share. */
4691         if (!set_share_security(service_name, psd)) {
4692                  DEBUG(0, ("process_usershare_file: Failed to set share "
4693                         "security for user share %s\n",
4694                         service_name ));
4695                 lp_remove_service(iService);
4696                 talloc_destroy(ctx);
4697                 return -1;
4698         }
4699
4700         talloc_destroy(ctx);
4701
4702         /* If from a template it may be marked invalid. */
4703         ServicePtrs[iService]->valid = True;
4704
4705         /* Set the service as a valid usershare. */
4706         ServicePtrs[iService]->usershare = USERSHARE_VALID;
4707
4708         /* Set guest access. */
4709         if (lp_usershare_allow_guests()) {
4710                 ServicePtrs[iService]->bGuest_ok = guest_ok;
4711         }
4712
4713         /* And note when it was loaded. */
4714         ServicePtrs[iService]->usershare_last_mod = sbuf.st_mtime;
4715         string_set(&ServicePtrs[iService]->szPath, sharepath);
4716         string_set(&ServicePtrs[iService]->comment, comment);
4717
4718         return iService;
4719 }
4720
4721 /***************************************************************************
4722  Checks if a usershare entry has been modified since last load.
4723 ***************************************************************************/
4724
4725 static BOOL usershare_exists(int iService, time_t *last_mod)
4726 {
4727         SMB_STRUCT_STAT lsbuf;
4728         const char *usersharepath = Globals.szUsersharePath;
4729         pstring fname;
4730
4731         pstrcpy(fname, usersharepath);
4732         pstrcat(fname, "/");
4733         pstrcat(fname, ServicePtrs[iService]->szService);
4734
4735         if (sys_lstat(fname, &lsbuf) != 0) {
4736                 return False;
4737         }
4738
4739         if (!S_ISREG(lsbuf.st_mode)) {
4740                 return False;
4741         }
4742
4743         *last_mod = lsbuf.st_mtime;
4744         return True;
4745 }
4746
4747 /***************************************************************************
4748  Load a usershare service by name. Returns a valid servicenumber or -1.
4749 ***************************************************************************/
4750
4751 int load_usershare_service(const char *servicename)
4752 {
4753         SMB_STRUCT_STAT sbuf;
4754         const char *usersharepath = Globals.szUsersharePath;
4755         int max_user_shares = Globals.iUsershareMaxShares;
4756         int snum_template = -1;
4757
4758         if (*usersharepath == 0 ||  max_user_shares == 0) {
4759                 return -1;
4760         }
4761
4762         if (sys_stat(usersharepath, &sbuf) != 0) {
4763                 DEBUG(0,("load_usershare_service: stat of %s failed. %s\n",
4764                         usersharepath, strerror(errno) ));
4765                 return -1;
4766         }
4767
4768         if (!S_ISDIR(sbuf.st_mode)) {
4769                 DEBUG(0,("load_usershare_service: %s is not a directory.\n",
4770                         usersharepath ));
4771                 return -1;
4772         }
4773
4774         /*
4775          * This directory must be owned by root, and have the 't' bit set.
4776          * It also must not be writable by "other".
4777          */
4778
4779 #ifdef S_ISVTX
4780         if (sbuf.st_uid != 0 || !(sbuf.st_mode & S_ISVTX) || (sbuf.st_mode & S_IWOTH)) {
4781 #else
4782         if (sbuf.st_uid != 0 || (sbuf.st_mode & S_IWOTH)) {
4783 #endif
4784                 DEBUG(0,("load_usershare_service: directory %s is not owned by root "
4785                         "or does not have the sticky bit 't' set or is writable by anyone.\n",
4786                         usersharepath ));
4787                 return -1;
4788         }
4789
4790         /* Ensure the template share exists if it's set. */
4791         if (Globals.szUsershareTemplateShare[0]) {
4792                 /* We can't use lp_servicenumber here as we are recommending that
4793                    template shares have -valid=False set. */
4794                 for (snum_template = iNumServices - 1; snum_template >= 0; snum_template--) {
4795                         if (ServicePtrs[snum_template]->szService &&
4796                                         strequal(ServicePtrs[snum_template]->szService,
4797                                                 Globals.szUsershareTemplateShare)) {
4798                                 break;
4799                         }
4800                 }
4801
4802                 if (snum_template == -1) {
4803                         DEBUG(0,("load_usershare_service: usershare template share %s "
4804                                 "does not exist.\n",
4805                                 Globals.szUsershareTemplateShare ));
4806                         return -1;
4807                 }
4808         }
4809
4810         return process_usershare_file(usersharepath, servicename, snum_template);
4811 }
4812
4813 /***************************************************************************
4814  Load all user defined shares from the user share directory.
4815  We only do this if we're enumerating the share list.
4816  This is the function that can delete usershares that have
4817  been removed.
4818 ***************************************************************************/
4819
4820 int load_usershare_shares(void)
4821 {
4822         SMB_STRUCT_DIR *dp;
4823         SMB_STRUCT_STAT sbuf;
4824         SMB_STRUCT_DIRENT *de;
4825         int num_usershares = 0;
4826         int max_user_shares = Globals.iUsershareMaxShares;
4827         unsigned int num_dir_entries, num_bad_dir_entries, num_tmp_dir_entries;
4828         unsigned int allowed_bad_entries = ((2*max_user_shares)/10);
4829         unsigned int allowed_tmp_entries = ((2*max_user_shares)/10);
4830         int iService;
4831         int snum_template = -1;
4832         const char *usersharepath = Globals.szUsersharePath;
4833         int ret = lp_numservices();
4834
4835         if (max_user_shares == 0 || *usersharepath == '\0') {
4836                 return lp_numservices();
4837         }
4838
4839         if (sys_stat(usersharepath, &sbuf) != 0) {
4840                 DEBUG(0,("load_usershare_shares: stat of %s failed. %s\n",
4841                         usersharepath, strerror(errno) ));
4842                 return ret;
4843         }
4844
4845         /*
4846          * This directory must be owned by root, and have the 't' bit set.
4847          * It also must not be writable by "other".
4848          */
4849
4850 #ifdef S_ISVTX
4851         if (sbuf.st_uid != 0 || !(sbuf.st_mode & S_ISVTX) || (sbuf.st_mode & S_IWOTH)) {
4852 #else
4853         if (sbuf.st_uid != 0 || (sbuf.st_mode & S_IWOTH)) {
4854 #endif
4855                 DEBUG(0,("load_usershare_shares: directory %s is not owned by root "
4856                         "or does not have the sticky bit 't' set or is writable by anyone.\n",
4857                         usersharepath ));
4858                 return ret;
4859         }
4860
4861         /* Ensure the template share exists if it's set. */
4862         if (Globals.szUsershareTemplateShare[0]) {
4863                 /* We can't use lp_servicenumber here as we are recommending that
4864                    template shares have -valid=False set. */
4865                 for (snum_template = iNumServices - 1; snum_template >= 0; snum_template--) {
4866                         if (ServicePtrs[snum_template]->szService &&
4867                                         strequal(ServicePtrs[snum_template]->szService,
4868                                                 Globals.szUsershareTemplateShare)) {
4869                                 break;
4870                         }
4871                 }
4872
4873                 if (snum_template == -1) {
4874                         DEBUG(0,("load_usershare_shares: usershare template share %s "
4875                                 "does not exist.\n",
4876                                 Globals.szUsershareTemplateShare ));
4877                         return ret;
4878                 }
4879         }
4880
4881         /* Mark all existing usershares as pending delete. */
4882         for (iService = iNumServices - 1; iService >= 0; iService--) {
4883                 if (VALID(iService) && ServicePtrs[iService]->usershare) {
4884                         ServicePtrs[iService]->usershare = USERSHARE_PENDING_DELETE;
4885                 }
4886         }
4887
4888         dp = sys_opendir(usersharepath);
4889         if (!dp) {
4890                 DEBUG(0,("load_usershare_shares:: failed to open directory %s. %s\n",
4891                         usersharepath, strerror(errno) ));
4892                 return ret;
4893         }
4894
4895         for (num_dir_entries = 0, num_bad_dir_entries = 0, num_tmp_dir_entries = 0;
4896                         (de = sys_readdir(dp));
4897                         num_dir_entries++ ) {
4898                 int r;
4899                 const char *n = de->d_name;
4900
4901                 /* Ignore . and .. */
4902                 if (*n == '.') {
4903                         if ((n[1] == '\0') || (n[1] == '.' && n[2] == '\0')) {
4904                                 continue;
4905                         }
4906                 }
4907
4908                 if (n[0] == ':') {
4909                         /* Temporary file used when creating a share. */
4910                         num_tmp_dir_entries++;
4911                 }
4912
4913                 /* Allow 20% tmp entries. */
4914                 if (num_tmp_dir_entries > allowed_tmp_entries) {
4915                         DEBUG(0,("load_usershare_shares: too many temp entries (%u) "
4916                                 "in directory %s\n",
4917                                 num_tmp_dir_entries, usersharepath));
4918                         break;
4919                 }
4920
4921                 r = process_usershare_file(usersharepath, n, snum_template);
4922                 if (r == 0) {
4923                         /* Update the services count. */
4924                         num_usershares++;
4925                         if (num_usershares >= max_user_shares) {
4926                                 DEBUG(0,("load_usershare_shares: max user shares reached "
4927                                         "on file %s in directory %s\n",
4928                                         n, usersharepath ));
4929                                 break;
4930                         }
4931                 } else if (r == -1) {
4932                         num_bad_dir_entries++;
4933                 }
4934
4935                 /* Allow 20% bad entries. */
4936                 if (num_bad_dir_entries > allowed_bad_entries) {
4937                         DEBUG(0,("load_usershare_shares: too many bad entries (%u) "
4938                                 "in directory %s\n",
4939                                 num_bad_dir_entries, usersharepath));
4940                         break;
4941                 }
4942
4943                 /* Allow 20% bad entries. */
4944                 if (num_dir_entries > max_user_shares + allowed_bad_entries) {
4945                         DEBUG(0,("load_usershare_shares: too many total entries (%u) "
4946                         "in directory %s\n",
4947                         num_dir_entries, usersharepath));
4948                         break;
4949                 }
4950         }
4951
4952         sys_closedir(dp);
4953
4954         /* Sweep through and delete any non-refreshed usershares that are
4955            not currently in use. */
4956         for (iService = iNumServices - 1; iService >= 0; iService--) {
4957                 if (VALID(iService) && (ServicePtrs[iService]->usershare == USERSHARE_PENDING_DELETE)) {
4958                         if (conn_snum_used(iService)) {
4959                                 continue;
4960                         }
4961                         /* Remove from the share ACL db. */
4962                         DEBUG(10,("load_usershare_shares: Removing deleted usershare %s\n",
4963                                 lp_servicename(iService) ));
4964                         delete_share_security(snum2params_static(iService));
4965                         free_service_byindex(iService);
4966                 }
4967         }
4968
4969         return lp_numservices();
4970 }
4971
4972 /********************************************************
4973  Destroy global resources allocated in this file
4974 ********************************************************/
4975
4976 void gfree_loadparm(void)
4977 {
4978         struct file_lists *f;
4979         struct file_lists *next;
4980         int i;
4981
4982         lp_TALLOC_FREE();
4983
4984         /* Free the file lists */
4985
4986         f = file_lists;
4987         while( f ) {
4988                 next = f->next;
4989                 SAFE_FREE( f->name );
4990                 SAFE_FREE( f->subfname );
4991                 SAFE_FREE( f );
4992                 f = next;
4993         }
4994
4995         /* Free resources allocated to services */
4996
4997         for ( i = 0; i < iNumServices; i++ ) {
4998                 if ( VALID(i) ) {
4999                         free_service_byindex(i);
5000                 }
5001         }
5002
5003         SAFE_FREE( ServicePtrs );
5004         iNumServices = 0;
5005
5006         /* Now release all resources allocated to global
5007            parameters and the default service */
5008
5009         for (i = 0; parm_table[i].label; i++) 
5010         {
5011                 if ( parm_table[i].type == P_STRING 
5012                         || parm_table[i].type == P_USTRING ) 
5013                 {
5014                         string_free( (char**)parm_table[i].ptr );
5015                 }
5016                 else if (parm_table[i].type == P_LIST) {
5017                         str_list_free( (char***)parm_table[i].ptr );
5018                 }
5019         }
5020 }
5021
5022 /***************************************************************************
5023  Load the services array from the services file. Return True on success, 
5024  False on failure.
5025 ***************************************************************************/
5026
5027 BOOL lp_load(const char *pszFname,
5028              BOOL global_only,
5029              BOOL save_defaults,
5030              BOOL add_ipc,
5031              BOOL initialize_globals)
5032 {
5033         pstring n2;
5034         BOOL bRetval;
5035         param_opt_struct *data, *pdata;
5036
5037         pstrcpy(n2, pszFname);
5038         
5039         standard_sub_basic( get_current_username(), current_user_info.domain,
5040                             n2,sizeof(n2) );
5041
5042         add_to_file_list(pszFname, n2);
5043
5044         bRetval = False;
5045
5046         DEBUG(3, ("lp_load: refreshing parameters\n"));
5047         
5048         bInGlobalSection = True;
5049         bGlobalOnly = global_only;
5050
5051         init_globals(! initialize_globals);
5052         debug_init();
5053
5054         if (save_defaults) {
5055                 init_locals();
5056                 lp_save_defaults();
5057         }
5058
5059         if (Globals.param_opt != NULL) {
5060                 data = Globals.param_opt;
5061                 while (data) {
5062                         string_free(&data->key);
5063                         string_free(&data->value);
5064                         str_list_free(&data->list);
5065                         pdata = data->next;
5066                         SAFE_FREE(data);
5067                         data = pdata;
5068                 }
5069                 Globals.param_opt = NULL;
5070         }
5071         
5072         /* We get sections first, so have to start 'behind' to make up */
5073         iServiceIndex = -1;
5074         bRetval = pm_process(n2, do_section, do_parameter);
5075
5076         /* finish up the last section */
5077         DEBUG(4, ("pm_process() returned %s\n", BOOLSTR(bRetval)));
5078         if (bRetval)
5079                 if (iServiceIndex >= 0)
5080                         bRetval = service_ok(iServiceIndex);
5081
5082         lp_add_auto_services(lp_auto_services());
5083
5084         if (add_ipc) {
5085                 /* When 'restrict anonymous = 2' guest connections to ipc$
5086                    are denied */
5087                 lp_add_ipc("IPC$", (lp_restrict_anonymous() < 2));
5088                 if ( lp_enable_asu_support() )
5089                         lp_add_ipc("ADMIN$", False);
5090         }
5091
5092         set_server_role();
5093         set_default_server_announce_type();
5094         set_allowed_client_auth();
5095
5096         bLoaded = True;
5097
5098         /* Now we check bWINSsupport and set szWINSserver to 127.0.0.1 */
5099         /* if bWINSsupport is true and we are in the client            */
5100         if (in_client && Globals.bWINSsupport) {
5101                 lp_do_parameter(GLOBAL_SECTION_SNUM, "wins server", "127.0.0.1");
5102         }
5103
5104         init_iconv();
5105
5106         return (bRetval);
5107 }
5108
5109 /***************************************************************************
5110  Reset the max number of services.
5111 ***************************************************************************/
5112
5113 void lp_resetnumservices(void)
5114 {
5115         iNumServices = 0;
5116 }
5117
5118 /***************************************************************************
5119  Return the max number of services.
5120 ***************************************************************************/
5121
5122 int lp_numservices(void)
5123 {
5124         return (iNumServices);
5125 }
5126
5127 /***************************************************************************
5128 Display the contents of the services array in human-readable form.
5129 ***************************************************************************/
5130
5131 void lp_dump(FILE *f, BOOL show_defaults, int maxtoprint)
5132 {
5133         int iService;
5134
5135         if (show_defaults)
5136                 defaults_saved = False;
5137
5138         dump_globals(f);
5139
5140         dump_a_service(&sDefault, f);
5141
5142         for (iService = 0; iService < maxtoprint; iService++) {
5143                 fprintf(f,"\n");
5144                 lp_dump_one(f, show_defaults, iService);
5145         }
5146 }
5147
5148 /***************************************************************************
5149 Display the contents of one service in human-readable form.
5150 ***************************************************************************/
5151
5152 void lp_dump_one(FILE * f, BOOL show_defaults, int snum)
5153 {
5154         if (VALID(snum)) {
5155                 if (ServicePtrs[snum]->szService[0] == '\0')
5156                         return;
5157                 dump_a_service(ServicePtrs[snum], f);
5158         }
5159 }
5160
5161 /***************************************************************************
5162 Return the number of the service with the given name, or -1 if it doesn't
5163 exist. Note that this is a DIFFERENT ANIMAL from the internal function
5164 getservicebyname()! This works ONLY if all services have been loaded, and
5165 does not copy the found service.
5166 ***************************************************************************/
5167
5168 int lp_servicenumber(const char *pszServiceName)
5169 {
5170         int iService;
5171         fstring serviceName;
5172         
5173         if (!pszServiceName) {
5174                 return GLOBAL_SECTION_SNUM;
5175         }
5176         
5177         for (iService = iNumServices - 1; iService >= 0; iService--) {
5178                 if (VALID(iService) && ServicePtrs[iService]->szService) {
5179                         /*
5180                          * The substitution here is used to support %U is
5181                          * service names
5182                          */
5183                         fstrcpy(serviceName, ServicePtrs[iService]->szService);
5184                         standard_sub_basic(get_current_username(),
5185                                            current_user_info.domain,
5186                                            serviceName,sizeof(serviceName));
5187                         if (strequal(serviceName, pszServiceName)) {
5188                                 break;
5189                         }
5190                 }
5191         }
5192
5193         if (iService >= 0 && ServicePtrs[iService]->usershare == USERSHARE_VALID) {
5194                 time_t last_mod;
5195
5196                 if (!usershare_exists(iService, &last_mod)) {
5197                         /* Remove the share security tdb entry for it. */
5198                         delete_share_security(snum2params_static(iService));
5199                         /* Remove it from the array. */
5200                         free_service_byindex(iService);
5201                         /* Doesn't exist anymore. */
5202                         return GLOBAL_SECTION_SNUM;
5203                 }
5204
5205                 /* Has it been modified ? If so delete and reload. */
5206                 if (ServicePtrs[iService]->usershare_last_mod < last_mod) {
5207                         /* Remove it from the array. */
5208                         free_service_byindex(iService);
5209                         /* and now reload it. */
5210                         iService = load_usershare_service(pszServiceName);
5211                 }
5212         }
5213
5214         if (iService < 0) {
5215                 DEBUG(7,("lp_servicenumber: couldn't find %s\n", pszServiceName));
5216                 return GLOBAL_SECTION_SNUM;
5217         }
5218
5219         return (iService);
5220 }
5221
5222 BOOL share_defined(const char *service_name)
5223 {
5224         return (lp_servicenumber(service_name) != -1);
5225 }
5226
5227 struct share_params *get_share_params(TALLOC_CTX *mem_ctx,
5228                                       const char *sharename)
5229 {
5230         struct share_params *result;
5231         char *sname;
5232         int snum;
5233
5234         if (!(sname = SMB_STRDUP(sharename))) {
5235                 return NULL;
5236         }
5237
5238         snum = find_service(sname);
5239         SAFE_FREE(sname);
5240
5241         if (snum < 0) {
5242                 return NULL;
5243         }
5244
5245         if (!(result = TALLOC_P(mem_ctx, struct share_params))) {
5246                 DEBUG(0, ("talloc failed\n"));
5247                 return NULL;
5248         }
5249
5250         result->service = snum;
5251         return result;
5252 }
5253
5254 struct share_iterator *share_list_all(TALLOC_CTX *mem_ctx)
5255 {
5256         struct share_iterator *result;
5257
5258         if (!(result = TALLOC_P(mem_ctx, struct share_iterator))) {
5259                 DEBUG(0, ("talloc failed\n"));
5260                 return NULL;
5261         }
5262
5263         result->next_id = 0;
5264         return result;
5265 }
5266
5267 struct share_params *next_share(struct share_iterator *list)
5268 {
5269         struct share_params *result;
5270
5271         while (!lp_snum_ok(list->next_id) &&
5272                (list->next_id < lp_numservices())) {
5273                 list->next_id += 1;
5274         }
5275
5276         if (list->next_id >= lp_numservices()) {
5277                 return NULL;
5278         }
5279
5280         if (!(result = TALLOC_P(list, struct share_params))) {
5281                 DEBUG(0, ("talloc failed\n"));
5282                 return NULL;
5283         }
5284
5285         result->service = list->next_id;
5286         list->next_id += 1;
5287         return result;
5288 }
5289
5290 struct share_params *next_printer(struct share_iterator *list)
5291 {
5292         struct share_params *result;
5293
5294         while ((result = next_share(list)) != NULL) {
5295                 if (lp_print_ok(result->service)) {
5296                         break;
5297                 }
5298         }
5299         return result;
5300 }
5301
5302 /*
5303  * This is a hack for a transition period until we transformed all code from
5304  * service numbers to struct share_params.
5305  */
5306
5307 struct share_params *snum2params_static(int snum)
5308 {
5309         static struct share_params result;
5310         result.service = snum;
5311         return &result;
5312 }
5313
5314 /*******************************************************************
5315  A useful volume label function. 
5316 ********************************************************************/
5317
5318 const char *volume_label(int snum)
5319 {
5320         char *ret;
5321         const char *label = lp_volume(snum);
5322         if (!*label) {
5323                 label = lp_servicename(snum);
5324         }
5325                 
5326         /* This returns a 33 byte guarenteed null terminated string. */
5327         ret = talloc_strndup(main_loop_talloc_get(), label, 32);
5328         if (!ret) {
5329                 return "";
5330         }               
5331         return ret;
5332 }
5333
5334 /*******************************************************************
5335  Set the server type we will announce as via nmbd.
5336 ********************************************************************/
5337
5338 static void set_default_server_announce_type(void)
5339 {
5340         default_server_announce = 0;
5341         default_server_announce |= SV_TYPE_WORKSTATION;
5342         default_server_announce |= SV_TYPE_SERVER;
5343         default_server_announce |= SV_TYPE_SERVER_UNIX;
5344
5345         /* note that the flag should be set only if we have a 
5346            printer service but nmbd doesn't actually load the 
5347            services so we can't tell   --jerry */
5348
5349         default_server_announce |= SV_TYPE_PRINTQ_SERVER;
5350
5351         switch (lp_announce_as()) {
5352                 case ANNOUNCE_AS_NT_SERVER:
5353                         default_server_announce |= SV_TYPE_SERVER_NT;
5354                         /* fall through... */
5355                 case ANNOUNCE_AS_NT_WORKSTATION:
5356                         default_server_announce |= SV_TYPE_NT;
5357                         break;
5358                 case ANNOUNCE_AS_WIN95:
5359                         default_server_announce |= SV_TYPE_WIN95_PLUS;
5360                         break;
5361                 case ANNOUNCE_AS_WFW:
5362                         default_server_announce |= SV_TYPE_WFW;
5363                         break;
5364                 default:
5365                         break;
5366         }
5367
5368         switch (lp_server_role()) {
5369                 case ROLE_DOMAIN_MEMBER:
5370                         default_server_announce |= SV_TYPE_DOMAIN_MEMBER;
5371                         break;
5372                 case ROLE_DOMAIN_PDC:
5373                         default_server_announce |= SV_TYPE_DOMAIN_CTRL;
5374                         break;
5375                 case ROLE_DOMAIN_BDC:
5376                         default_server_announce |= SV_TYPE_DOMAIN_BAKCTRL;
5377                         break;
5378                 case ROLE_STANDALONE:
5379                 default:
5380                         break;
5381         }
5382         if (lp_time_server())
5383                 default_server_announce |= SV_TYPE_TIME_SOURCE;
5384
5385         if (lp_host_msdfs())
5386                 default_server_announce |= SV_TYPE_DFS_SERVER;
5387 }
5388
5389 /***********************************************************
5390  returns role of Samba server
5391 ************************************************************/
5392
5393 int lp_server_role(void)
5394 {
5395         return server_role;
5396 }
5397
5398 /***********************************************************
5399  If we are PDC then prefer us as DMB
5400 ************************************************************/
5401
5402 BOOL lp_domain_master(void)
5403 {
5404         if (Globals.bDomainMaster == Auto)
5405                 return (lp_server_role() == ROLE_DOMAIN_PDC);
5406
5407         return Globals.bDomainMaster;
5408 }
5409
5410 /***********************************************************
5411  If we are DMB then prefer us as LMB
5412 ************************************************************/
5413
5414 BOOL lp_preferred_master(void)
5415 {
5416         if (Globals.bPreferredMaster == Auto)
5417                 return (lp_local_master() && lp_domain_master());
5418
5419         return Globals.bPreferredMaster;
5420 }
5421
5422 /*******************************************************************
5423  Remove a service.
5424 ********************************************************************/
5425
5426 void lp_remove_service(int snum)
5427 {
5428         ServicePtrs[snum]->valid = False;
5429         invalid_services[num_invalid_services++] = snum;
5430 }
5431
5432 /*******************************************************************
5433  Copy a service.
5434 ********************************************************************/
5435
5436 void lp_copy_service(int snum, const char *new_name)
5437 {
5438         do_section(new_name);
5439         if (snum >= 0) {
5440                 snum = lp_servicenumber(new_name);
5441                 if (snum >= 0)
5442                         lp_do_parameter(snum, "copy", lp_servicename(snum));
5443         }
5444 }
5445
5446
5447 /*******************************************************************
5448  Get the default server type we will announce as via nmbd.
5449 ********************************************************************/
5450
5451 int lp_default_server_announce(void)
5452 {
5453         return default_server_announce;
5454 }
5455
5456 /*******************************************************************
5457  Split the announce version into major and minor numbers.
5458 ********************************************************************/
5459
5460 int lp_major_announce_version(void)
5461 {
5462         static BOOL got_major = False;
5463         static int major_version = DEFAULT_MAJOR_VERSION;
5464         char *vers;
5465         char *p;
5466
5467         if (got_major)
5468                 return major_version;
5469
5470         got_major = True;
5471         if ((vers = lp_announce_version()) == NULL)
5472                 return major_version;
5473
5474         if ((p = strchr_m(vers, '.')) == 0)
5475                 return major_version;
5476
5477         *p = '\0';
5478         major_version = atoi(vers);
5479         return major_version;
5480 }
5481
5482 int lp_minor_announce_version(void)
5483 {
5484         static BOOL got_minor = False;
5485         static int minor_version = DEFAULT_MINOR_VERSION;
5486         char *vers;
5487         char *p;
5488
5489         if (got_minor)
5490                 return minor_version;
5491
5492         got_minor = True;
5493         if ((vers = lp_announce_version()) == NULL)
5494                 return minor_version;
5495
5496         if ((p = strchr_m(vers, '.')) == 0)
5497                 return minor_version;
5498
5499         p++;
5500         minor_version = atoi(p);
5501         return minor_version;
5502 }
5503
5504 /***********************************************************
5505  Set the global name resolution order (used in smbclient).
5506 ************************************************************/
5507
5508 void lp_set_name_resolve_order(const char *new_order)
5509 {
5510         string_set(&Globals.szNameResolveOrder, new_order);
5511 }
5512
5513 const char *lp_printername(int snum)
5514 {
5515         const char *ret = _lp_printername(snum);
5516         if (ret == NULL || (ret != NULL && *ret == '\0'))
5517                 ret = lp_const_servicename(snum);
5518
5519         return ret;
5520 }
5521
5522
5523 /***********************************************************
5524  Allow daemons such as winbindd to fix their logfile name.
5525 ************************************************************/
5526
5527 void lp_set_logfile(const char *name)
5528 {
5529         string_set(&Globals.szLogFile, name);
5530         pstrcpy(debugf, name);
5531 }
5532
5533 /*******************************************************************
5534  Return the max print jobs per queue.
5535 ********************************************************************/
5536
5537 int lp_maxprintjobs(int snum)
5538 {
5539         int maxjobs = LP_SNUM_OK(snum) ? ServicePtrs[snum]->iMaxPrintJobs : sDefault.iMaxPrintJobs;
5540         if (maxjobs <= 0 || maxjobs >= PRINT_MAX_JOBID)
5541                 maxjobs = PRINT_MAX_JOBID - 1;
5542
5543         return maxjobs;
5544 }
5545
5546 const char *lp_printcapname(void)
5547 {
5548         if ((Globals.szPrintcapname != NULL) &&
5549             (Globals.szPrintcapname[0] != '\0'))
5550                 return Globals.szPrintcapname;
5551
5552         if (sDefault.iPrinting == PRINT_CUPS) {
5553 #ifdef HAVE_CUPS
5554                 return "cups";
5555 #else
5556                 return "lpstat";
5557 #endif
5558         }
5559
5560         if (sDefault.iPrinting == PRINT_BSD)
5561                 return "/etc/printcap";
5562
5563         return PRINTCAP_NAME;
5564 }
5565
5566 /*******************************************************************
5567  Ensure we don't use sendfile if server smb signing is active.
5568 ********************************************************************/
5569
5570 static uint32 spoolss_state;
5571
5572 BOOL lp_disable_spoolss( void )
5573 {
5574         if ( spoolss_state == SVCCTL_STATE_UNKNOWN )
5575                 spoolss_state = _lp_disable_spoolss() ? SVCCTL_STOPPED : SVCCTL_RUNNING;
5576
5577         return spoolss_state == SVCCTL_STOPPED ? True : False;
5578 }
5579
5580 void lp_set_spoolss_state( uint32 state )
5581 {
5582         SMB_ASSERT( (state == SVCCTL_STOPPED) || (state == SVCCTL_RUNNING) );
5583
5584         spoolss_state = state;
5585 }
5586
5587 uint32 lp_get_spoolss_state( void )
5588 {
5589         return lp_disable_spoolss() ? SVCCTL_STOPPED : SVCCTL_RUNNING;
5590 }
5591
5592 /*******************************************************************
5593  Ensure we don't use sendfile if server smb signing is active.
5594 ********************************************************************/
5595
5596 BOOL lp_use_sendfile(int snum)
5597 {
5598         /* Using sendfile blows the brains out of any DOS or Win9x TCP stack... JRA. */
5599         if (Protocol < PROTOCOL_NT1) {
5600                 return False;
5601         }
5602         return (_lp_use_sendfile(snum) && (get_remote_arch() != RA_WIN95) && !srv_is_signing_active());
5603 }
5604
5605 /*******************************************************************
5606  Turn off sendfile if we find the underlying OS doesn't support it.
5607 ********************************************************************/
5608
5609 void set_use_sendfile(int snum, BOOL val)
5610 {
5611         if (LP_SNUM_OK(snum))
5612                 ServicePtrs[snum]->bUseSendfile = val;
5613         else
5614                 sDefault.bUseSendfile = val;
5615 }
5616
5617 /*******************************************************************
5618  Turn off storing DOS attributes if this share doesn't support it.
5619 ********************************************************************/
5620
5621 void set_store_dos_attributes(int snum, BOOL val)
5622 {
5623         if (!LP_SNUM_OK(snum))
5624                 return;
5625         ServicePtrs[(snum)]->bStoreDosAttributes = val;
5626 }
5627
5628 void lp_set_mangling_method(const char *new_method)
5629 {
5630         string_set(&Globals.szManglingMethod, new_method);
5631 }
5632
5633 /*******************************************************************
5634  Global state for POSIX pathname processing.
5635 ********************************************************************/
5636
5637 static BOOL posix_pathnames;
5638
5639 BOOL lp_posix_pathnames(void)
5640 {
5641         return posix_pathnames;
5642 }
5643
5644 /*******************************************************************
5645  Change everything needed to ensure POSIX pathname processing (currently
5646  not much).
5647 ********************************************************************/
5648
5649 void lp_set_posix_pathnames(void)
5650 {
5651         posix_pathnames = True;
5652 }
5653
5654 /*******************************************************************
5655  Global state for POSIX lock processing - CIFS unix extensions.
5656 ********************************************************************/
5657
5658 BOOL posix_default_lock_was_set;
5659 static enum brl_flavour posix_cifsx_locktype; /* By default 0 == WINDOWS_LOCK */
5660
5661 enum brl_flavour lp_posix_cifsu_locktype(files_struct *fsp)
5662 {
5663         if (posix_default_lock_was_set) {
5664                 return posix_cifsx_locktype;
5665         } else {
5666                 return fsp->posix_open ? POSIX_LOCK : WINDOWS_LOCK;
5667         }
5668 }
5669
5670 /*******************************************************************
5671 ********************************************************************/
5672
5673 void lp_set_posix_default_cifsx_readwrite_locktype(enum brl_flavour val)
5674 {
5675         posix_default_lock_was_set = True;
5676         posix_cifsx_locktype = val;
5677 }