d646a79334900335f330370aad72932a56a6ef84
[jra/samba/.git] / source3 / param / loadparm.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Parameter loading functions
4    Copyright (C) Karl Auer 1993-1998
5
6    Largely re-written by Andrew Tridgell, September 1994
7
8    Copyright (C) Simo Sorce 2001
9    Copyright (C) Alexander Bokovoy 2002
10    Copyright (C) Stefan (metze) Metzmacher 2002
11    Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2003
12    Copyright (C) Michael Adam 2008
13    
14    This program is free software; you can redistribute it and/or modify
15    it under the terms of the GNU General Public License as published by
16    the Free Software Foundation; either version 3 of the License, or
17    (at your option) any later version.
18    
19    This program is distributed in the hope that it will be useful,
20    but WITHOUT ANY WARRANTY; without even the implied warranty of
21    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22    GNU General Public License for more details.
23    
24    You should have received a copy of the GNU General Public License
25    along with this program.  If not, see <http://www.gnu.org/licenses/>.
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 #include "printing.h"
56
57 bool bLoaded = False;
58
59 extern enum protocol_types Protocol;
60 extern userdom_struct current_user_info;
61
62 #ifndef GLOBAL_NAME
63 #define GLOBAL_NAME "global"
64 #endif
65
66 #ifndef PRINTERS_NAME
67 #define PRINTERS_NAME "printers"
68 #endif
69
70 #ifndef HOMES_NAME
71 #define HOMES_NAME "homes"
72 #endif
73
74 /* the special value for the include parameter
75  * to be interpreted not as a file name but to
76  * trigger loading of the global smb.conf options
77  * from registry. */
78 #ifndef INCLUDE_REGISTRY_NAME
79 #define INCLUDE_REGISTRY_NAME "registry"
80 #endif
81
82 static bool in_client = False;          /* Not in the client by default */
83 static struct smbconf_csn conf_last_csn;
84
85 #define CONFIG_BACKEND_FILE 0
86 #define CONFIG_BACKEND_REGISTRY 1
87
88 static int config_backend = CONFIG_BACKEND_FILE;
89
90 /* some helpful bits */
91 #define LP_SNUM_OK(i) (((i) >= 0) && ((i) < iNumServices) && (ServicePtrs != NULL) && ServicePtrs[(i)]->valid)
92 #define VALID(i) (ServicePtrs != NULL && ServicePtrs[i]->valid)
93
94 #define USERSHARE_VALID 1
95 #define USERSHARE_PENDING_DELETE 2
96
97 extern int extra_time_offset;
98
99 static bool defaults_saved = False;
100
101 struct param_opt_struct {
102         struct param_opt_struct *prev, *next;
103         char *key;
104         char *value;
105         char **list;
106 };
107
108 /*
109  * This structure describes global (ie., server-wide) parameters.
110  */
111 struct global {
112         int ConfigBackend;
113         char *smb_ports;
114         char *dos_charset;
115         char *unix_charset;
116         char *display_charset;
117         char *szPrintcapname;
118         char *szAddPortCommand;
119         char *szEnumPortsCommand;
120         char *szAddPrinterCommand;
121         char *szDeletePrinterCommand;
122         char *szOs2DriverMap;
123         char *szLockDir;
124         char *szPidDir;
125         char *szRootdir;
126         char *szDefaultService;
127         char *szGetQuota;
128         char *szSetQuota;
129         char *szMsgCommand;
130         char *szServerString;
131         char *szAutoServices;
132         char *szPasswdProgram;
133         char *szPasswdChat;
134         char *szLogFile;
135         char *szConfigFile;
136         char *szSMBPasswdFile;
137         char *szPrivateDir;
138         char *szPassdbBackend;
139         char **szPreloadModules;
140         char *szPasswordServer;
141         char *szSocketOptions;
142         char *szRealm;
143         char *szAfsUsernameMap;
144         int iAfsTokenLifetime;
145         char *szLogNtTokenCommand;
146         char *szUsernameMap;
147         char *szLogonScript;
148         char *szLogonPath;
149         char *szLogonDrive;
150         char *szLogonHome;
151         char **szWINSservers;
152         char **szInterfaces;
153         char *szRemoteAnnounce;
154         char *szRemoteBrowseSync;
155         char *szSocketAddress;
156         char *szNISHomeMapName;
157         char *szAnnounceVersion;        /* This is initialised in init_globals */
158         char *szWorkgroup;
159         char *szNetbiosName;
160         char **szNetbiosAliases;
161         char *szNetbiosScope;
162         char *szNameResolveOrder;
163         char *szPanicAction;
164         char *szAddUserScript;
165         char *szRenameUserScript;
166         char *szDelUserScript;
167         char *szAddGroupScript;
168         char *szDelGroupScript;
169         char *szAddUserToGroupScript;
170         char *szDelUserFromGroupScript;
171         char *szSetPrimaryGroupScript;
172         char *szAddMachineScript;
173         char *szShutdownScript;
174         char *szAbortShutdownScript;
175         char *szUsernameMapScript;
176         char *szCheckPasswordScript;
177         char *szWINSHook;
178         char *szUtmpDir;
179         char *szWtmpDir;
180         bool bUtmp;
181         char *szIdmapUID;
182         char *szIdmapGID;
183         bool bPassdbExpandExplicit;
184         int AlgorithmicRidBase;
185         char *szTemplateHomedir;
186         char *szTemplateShell;
187         char *szWinbindSeparator;
188         bool bWinbindEnumUsers;
189         bool bWinbindEnumGroups;
190         bool bWinbindUseDefaultDomain;
191         bool bWinbindTrustedDomainsOnly;
192         bool bWinbindNestedGroups;
193         int  winbind_expand_groups;
194         bool bWinbindRefreshTickets;
195         bool bWinbindOfflineLogon;
196         bool bWinbindNormalizeNames;
197         bool bWinbindRpcOnly;
198         char *szIdmapBackend;
199         char *szIdmapAllocBackend;
200         char *szAddShareCommand;
201         char *szChangeShareCommand;
202         char *szDeleteShareCommand;
203         char **szEventLogs;
204         char *szGuestaccount;
205         char *szManglingMethod;
206         char **szServicesList;
207         char *szUsersharePath;
208         char *szUsershareTemplateShare;
209         char **szUsersharePrefixAllowList;
210         char **szUsersharePrefixDenyList;
211         int mangle_prefix;
212         int max_log_size;
213         char *szLogLevel;
214         int max_xmit;
215         int max_mux;
216         int max_open_files;
217         int open_files_db_hash_size;
218         int pwordlevel;
219         int unamelevel;
220         int deadtime;
221         bool getwd_cache;
222         int maxprotocol;
223         int minprotocol;
224         int security;
225         char **AuthMethods;
226         bool paranoid_server_security;
227         int maxdisksize;
228         int lpqcachetime;
229         int iMaxSmbdProcesses;
230         bool bDisableSpoolss;
231         int syslog;
232         int os_level;
233         bool enhanced_browsing;
234         int max_ttl;
235         int max_wins_ttl;
236         int min_wins_ttl;
237         int lm_announce;
238         int lm_interval;
239         int announce_as;        /* This is initialised in init_globals */
240         int machine_password_timeout;
241         int map_to_guest;
242         int oplock_break_wait_time;
243         int winbind_cache_time;
244         int winbind_reconnect_delay;
245         int winbind_max_idle_children;
246         char **szWinbindNssInfo;
247         int iLockSpinTime;
248         char *szLdapMachineSuffix;
249         char *szLdapUserSuffix;
250         char *szLdapIdmapSuffix;
251         char *szLdapGroupSuffix;
252         int ldap_ssl;
253         char *szLdapSuffix;
254         char *szLdapAdminDn;
255         int ldap_debug_level;
256         int ldap_debug_threshold;
257         int iAclCompat;
258         char *szCupsServer;
259         char *szIPrintServer;
260         char *ctdbdSocket;
261         char **szClusterAddresses;
262         bool clustering;
263         int ldap_passwd_sync;
264         int ldap_replication_sleep;
265         int ldap_timeout; /* This is initialised in init_globals */
266         int ldap_connection_timeout;
267         int ldap_page_size;
268         bool ldap_delete_dn;
269         bool bMsAddPrinterWizard;
270         bool bDNSproxy;
271         bool bWINSsupport;
272         bool bWINSproxy;
273         bool bLocalMaster;
274         int  iPreferredMaster;
275         int iDomainMaster;
276         bool bDomainLogons;
277         char **szInitLogonDelayedHosts;
278         int InitLogonDelay;
279         bool bEncryptPasswords;
280         bool bUpdateEncrypt;
281         int  clientSchannel;
282         int  serverSchannel;
283         bool bNullPasswords;
284         bool bObeyPamRestrictions;
285         bool bLoadPrinters;
286         int PrintcapCacheTime;
287         bool bLargeReadwrite;
288         bool bReadRaw;
289         bool bWriteRaw;
290         bool bSyslogOnly;
291         bool bBrowseList;
292         bool bNISHomeMap;
293         bool bTimeServer;
294         bool bBindInterfacesOnly;
295         bool bPamPasswordChange;
296         bool bUnixPasswdSync;
297         bool bPasswdChatDebug;
298         int iPasswdChatTimeout;
299         bool bTimestampLogs;
300         bool bNTSmbSupport;
301         bool bNTPipeSupport;
302         bool bNTStatusSupport;
303         bool bStatCache;
304         int iMaxStatCacheSize;
305         bool bKernelOplocks;
306         bool bAllowTrustedDomains;
307         bool bLanmanAuth;
308         bool bNTLMAuth;
309         bool bUseSpnego;
310         bool bClientLanManAuth;
311         bool bClientNTLMv2Auth;
312         bool bClientPlaintextAuth;
313         bool bClientUseSpnego;
314         bool bDebugPrefixTimestamp;
315         bool bDebugHiresTimestamp;
316         bool bDebugPid;
317         bool bDebugUid;
318         bool bDebugClass;
319         bool bEnableCoreFiles;
320         bool bHostMSDfs;
321         bool bUseMmap;
322         bool bHostnameLookups;
323         bool bUnixExtensions;
324         bool bDisableNetbios;
325         bool bUseKerberosKeytab;
326         bool bDeferSharingViolations;
327         bool bEnablePrivileges;
328         bool bASUSupport;
329         bool bUsershareOwnerOnly;
330         bool bUsershareAllowGuests;
331         bool bRegistryShares;
332         int restrict_anonymous;
333         int name_cache_timeout;
334         int client_signing;
335         int server_signing;
336         int client_ldap_sasl_wrapping;
337         int iUsershareMaxShares;
338         int iIdmapCacheTime;
339         int iIdmapNegativeCacheTime;
340         bool bResetOnZeroVC;
341         int iKeepalive;
342         int iminreceivefile;
343         struct param_opt_struct *param_opt;
344         int cups_connection_timeout;
345 };
346
347 static struct global Globals;
348
349 /*
350  * This structure describes a single service.
351  */
352 struct service {
353         bool valid;
354         bool autoloaded;
355         int usershare;
356         time_t usershare_last_mod;
357         char *szService;
358         char *szPath;
359         char *szUsername;
360         char **szInvalidUsers;
361         char **szValidUsers;
362         char **szAdminUsers;
363         char *szCopy;
364         char *szInclude;
365         char *szPreExec;
366         char *szPostExec;
367         char *szRootPreExec;
368         char *szRootPostExec;
369         char *szCupsOptions;
370         char *szPrintcommand;
371         char *szLpqcommand;
372         char *szLprmcommand;
373         char *szLppausecommand;
374         char *szLpresumecommand;
375         char *szQueuepausecommand;
376         char *szQueueresumecommand;
377         char *szPrintername;
378         char *szPrintjobUsername;
379         char *szDontdescend;
380         char **szHostsallow;
381         char **szHostsdeny;
382         char *szMagicScript;
383         char *szMagicOutput;
384         char *szVetoFiles;
385         char *szHideFiles;
386         char *szVetoOplockFiles;
387         char *comment;
388         char *force_user;
389         char *force_group;
390         char **readlist;
391         char **writelist;
392         char **printer_admin;
393         char *volume;
394         char *fstype;
395         char **szVfsObjects;
396         char *szMSDfsProxy;
397         char *szAioWriteBehind;
398         char *szDfree;
399         int iMinPrintSpace;
400         int iMaxPrintJobs;
401         int iMaxReportedPrintJobs;
402         int iWriteCacheSize;
403         int iCreate_mask;
404         int iCreate_force_mode;
405         int iSecurity_mask;
406         int iSecurity_force_mode;
407         int iDir_mask;
408         int iDir_force_mode;
409         int iDir_Security_mask;
410         int iDir_Security_force_mode;
411         int iMaxConnections;
412         int iDefaultCase;
413         int iPrinting;
414         int iOplockContentionLimit;
415         int iCSCPolicy;
416         int iBlock_size;
417         int iDfreeCacheTime;
418         bool bPreexecClose;
419         bool bRootpreexecClose;
420         int  iCaseSensitive;
421         bool bCasePreserve;
422         bool bShortCasePreserve;
423         bool bHideDotFiles;
424         bool bHideSpecialFiles;
425         bool bHideUnReadable;
426         bool bHideUnWriteableFiles;
427         bool bBrowseable;
428         bool bAvailable;
429         bool bRead_only;
430         bool bNo_set_dir;
431         bool bGuest_only;
432         bool bAdministrative_share;
433         bool bGuest_ok;
434         bool bPrint_ok;
435         bool bMap_system;
436         bool bMap_hidden;
437         bool bMap_archive;
438         bool bStoreDosAttributes;
439         bool bDmapiSupport;
440         bool bLocking;
441         int iStrictLocking;
442         bool bPosixLocking;
443         bool bShareModes;
444         bool bOpLocks;
445         bool bLevel2OpLocks;
446         bool bOnlyUser;
447         bool bMangledNames;
448         bool bWidelinks;
449         bool bSymlinks;
450         bool bSyncAlways;
451         bool bStrictAllocate;
452         bool bStrictSync;
453         char magic_char;
454         struct bitmap *copymap;
455         bool bDeleteReadonly;
456         bool bFakeOplocks;
457         bool bDeleteVetoFiles;
458         bool bDosFilemode;
459         bool bDosFiletimes;
460         bool bDosFiletimeResolution;
461         bool bFakeDirCreateTimes;
462         bool bBlockingLocks;
463         bool bInheritPerms;
464         bool bInheritACLS;
465         bool bInheritOwner;
466         bool bMSDfsRoot;
467         bool bUseClientDriver;
468         bool bDefaultDevmode;
469         bool bForcePrintername;
470         bool bNTAclSupport;
471         bool bForceUnknownAclUser;
472         bool bUseSendfile;
473         bool bProfileAcls;
474         bool bMap_acl_inherit;
475         bool bAfs_Share;
476         bool bEASupport;
477         bool bAclCheckPermissions;
478         bool bAclMapFullControl;
479         bool bAclGroupControl;
480         bool bChangeNotify;
481         bool bKernelChangeNotify;
482         int iallocation_roundup_size;
483         int iAioReadSize;
484         int iAioWriteSize;
485         int iMap_readonly;
486         int iDirectoryNameCacheSize;
487         int ismb_encrypt;
488         struct param_opt_struct *param_opt;
489
490         char dummy[3];          /* for alignment */
491 };
492
493
494 /* This is a default service used to prime a services structure */
495 static struct service sDefault = {
496         True,                   /* valid */
497         False,                  /* not autoloaded */
498         0,                      /* not a usershare */
499         (time_t)0,              /* No last mod time */
500         NULL,                   /* szService */
501         NULL,                   /* szPath */
502         NULL,                   /* szUsername */
503         NULL,                   /* szInvalidUsers */
504         NULL,                   /* szValidUsers */
505         NULL,                   /* szAdminUsers */
506         NULL,                   /* szCopy */
507         NULL,                   /* szInclude */
508         NULL,                   /* szPreExec */
509         NULL,                   /* szPostExec */
510         NULL,                   /* szRootPreExec */
511         NULL,                   /* szRootPostExec */
512         NULL,                   /* szCupsOptions */
513         NULL,                   /* szPrintcommand */
514         NULL,                   /* szLpqcommand */
515         NULL,                   /* szLprmcommand */
516         NULL,                   /* szLppausecommand */
517         NULL,                   /* szLpresumecommand */
518         NULL,                   /* szQueuepausecommand */
519         NULL,                   /* szQueueresumecommand */
520         NULL,                   /* szPrintername */
521         NULL,                   /* szPrintjobUsername */
522         NULL,                   /* szDontdescend */
523         NULL,                   /* szHostsallow */
524         NULL,                   /* szHostsdeny */
525         NULL,                   /* szMagicScript */
526         NULL,                   /* szMagicOutput */
527         NULL,                   /* szVetoFiles */
528         NULL,                   /* szHideFiles */
529         NULL,                   /* szVetoOplockFiles */
530         NULL,                   /* comment */
531         NULL,                   /* force user */
532         NULL,                   /* force group */
533         NULL,                   /* readlist */
534         NULL,                   /* writelist */
535         NULL,                   /* printer admin */
536         NULL,                   /* volume */
537         NULL,                   /* fstype */
538         NULL,                   /* vfs objects */
539         NULL,                   /* szMSDfsProxy */
540         NULL,                   /* szAioWriteBehind */
541         NULL,                   /* szDfree */
542         0,                      /* iMinPrintSpace */
543         1000,                   /* iMaxPrintJobs */
544         0,                      /* iMaxReportedPrintJobs */
545         0,                      /* iWriteCacheSize */
546         0744,                   /* iCreate_mask */
547         0000,                   /* iCreate_force_mode */
548         0777,                   /* iSecurity_mask */
549         0,                      /* iSecurity_force_mode */
550         0755,                   /* iDir_mask */
551         0000,                   /* iDir_force_mode */
552         0777,                   /* iDir_Security_mask */
553         0,                      /* iDir_Security_force_mode */
554         0,                      /* iMaxConnections */
555         CASE_LOWER,             /* iDefaultCase */
556         DEFAULT_PRINTING,       /* iPrinting */
557         2,                      /* iOplockContentionLimit */
558         0,                      /* iCSCPolicy */
559         1024,                   /* iBlock_size */
560         0,                      /* iDfreeCacheTime */
561         False,                  /* bPreexecClose */
562         False,                  /* bRootpreexecClose */
563         Auto,                   /* case sensitive */
564         True,                   /* case preserve */
565         True,                   /* short case preserve */
566         True,                   /* bHideDotFiles */
567         False,                  /* bHideSpecialFiles */
568         False,                  /* bHideUnReadable */
569         False,                  /* bHideUnWriteableFiles */
570         True,                   /* bBrowseable */
571         True,                   /* bAvailable */
572         True,                   /* bRead_only */
573         True,                   /* bNo_set_dir */
574         False,                  /* bGuest_only */
575         False,                  /* bAdministrative_share */
576         False,                  /* bGuest_ok */
577         False,                  /* bPrint_ok */
578         False,                  /* bMap_system */
579         False,                  /* bMap_hidden */
580         True,                   /* bMap_archive */
581         False,                  /* bStoreDosAttributes */
582         False,                  /* bDmapiSupport */
583         True,                   /* bLocking */
584         Auto,                   /* iStrictLocking */
585         True,                   /* bPosixLocking */
586         True,                   /* bShareModes */
587         True,                   /* bOpLocks */
588         True,                   /* bLevel2OpLocks */
589         False,                  /* bOnlyUser */
590         True,                   /* bMangledNames */
591         True,                   /* bWidelinks */
592         True,                   /* bSymlinks */
593         False,                  /* bSyncAlways */
594         False,                  /* bStrictAllocate */
595         False,                  /* bStrictSync */
596         '~',                    /* magic char */
597         NULL,                   /* copymap */
598         False,                  /* bDeleteReadonly */
599         False,                  /* bFakeOplocks */
600         False,                  /* bDeleteVetoFiles */
601         False,                  /* bDosFilemode */
602         True,                   /* bDosFiletimes */
603         False,                  /* bDosFiletimeResolution */
604         False,                  /* bFakeDirCreateTimes */
605         True,                   /* bBlockingLocks */
606         False,                  /* bInheritPerms */
607         False,                  /* bInheritACLS */
608         False,                  /* bInheritOwner */
609         False,                  /* bMSDfsRoot */
610         False,                  /* bUseClientDriver */
611         True,                   /* bDefaultDevmode */
612         False,                  /* bForcePrintername */
613         True,                   /* bNTAclSupport */
614         False,                  /* bForceUnknownAclUser */
615         False,                  /* bUseSendfile */
616         False,                  /* bProfileAcls */
617         False,                  /* bMap_acl_inherit */
618         False,                  /* bAfs_Share */
619         False,                  /* bEASupport */
620         True,                   /* bAclCheckPermissions */
621         True,                   /* bAclMapFullControl */
622         False,                  /* bAclGroupControl */
623         True,                   /* bChangeNotify */
624         True,                   /* bKernelChangeNotify */
625         SMB_ROUNDUP_ALLOCATION_SIZE,            /* iallocation_roundup_size */
626         0,                      /* iAioReadSize */
627         0,                      /* iAioWriteSize */
628         MAP_READONLY_YES,       /* iMap_readonly */
629 #ifdef BROKEN_DIRECTORY_HANDLING
630         0,                      /* iDirectoryNameCacheSize */
631 #else
632         100,                    /* iDirectoryNameCacheSize */
633 #endif
634         Auto,                   /* ismb_encrypt */
635         NULL,                   /* Parametric options */
636
637         ""                      /* dummy */
638 };
639
640 /* local variables */
641 static struct service **ServicePtrs = NULL;
642 static int iNumServices = 0;
643 static int iServiceIndex = 0;
644 static struct db_context *ServiceHash;
645 static int *invalid_services = NULL;
646 static int num_invalid_services = 0;
647 static bool bInGlobalSection = True;
648 static bool bGlobalOnly = False;
649 static int server_role;
650 static int default_server_announce;
651
652 #define NUMPARAMETERS (sizeof(parm_table) / sizeof(struct parm_struct))
653
654 /* prototypes for the special type handlers */
655 static bool handle_include( int snum, const char *pszParmValue, char **ptr);
656 static bool handle_copy( int snum, const char *pszParmValue, char **ptr);
657 static bool handle_netbios_name( int snum, const char *pszParmValue, char **ptr);
658 static bool handle_idmap_uid( int snum, const char *pszParmValue, char **ptr);
659 static bool handle_idmap_gid( int snum, const char *pszParmValue, char **ptr);
660 static bool handle_debug_list( int snum, const char *pszParmValue, char **ptr );
661 static bool handle_workgroup( int snum, const char *pszParmValue, char **ptr );
662 static bool handle_netbios_aliases( int snum, const char *pszParmValue, char **ptr );
663 static bool handle_netbios_scope( int snum, const char *pszParmValue, char **ptr );
664 static bool handle_charset( int snum, const char *pszParmValue, char **ptr );
665 static bool handle_printing( int snum, const char *pszParmValue, char **ptr);
666 static bool handle_ldap_debug_level( int snum, const char *pszParmValue, char **ptr);
667
668 static void set_server_role(void);
669 static void set_default_server_announce_type(void);
670 static void set_allowed_client_auth(void);
671
672 static const struct enum_list enum_protocol[] = {
673         {PROTOCOL_NT1, "NT1"},
674         {PROTOCOL_LANMAN2, "LANMAN2"},
675         {PROTOCOL_LANMAN1, "LANMAN1"},
676         {PROTOCOL_CORE, "CORE"},
677         {PROTOCOL_COREPLUS, "COREPLUS"},
678         {PROTOCOL_COREPLUS, "CORE+"},
679         {-1, NULL}
680 };
681
682 static const struct enum_list enum_security[] = {
683         {SEC_SHARE, "SHARE"},
684         {SEC_USER, "USER"},
685         {SEC_SERVER, "SERVER"},
686         {SEC_DOMAIN, "DOMAIN"},
687 #ifdef HAVE_ADS
688         {SEC_ADS, "ADS"},
689 #endif
690         {-1, NULL}
691 };
692
693 static const struct enum_list enum_printing[] = {
694         {PRINT_SYSV, "sysv"},
695         {PRINT_AIX, "aix"},
696         {PRINT_HPUX, "hpux"},
697         {PRINT_BSD, "bsd"},
698         {PRINT_QNX, "qnx"},
699         {PRINT_PLP, "plp"},
700         {PRINT_LPRNG, "lprng"},
701         {PRINT_CUPS, "cups"},
702         {PRINT_IPRINT, "iprint"},
703         {PRINT_LPRNT, "nt"},
704         {PRINT_LPROS2, "os2"},
705 #ifdef DEVELOPER
706         {PRINT_TEST, "test"},
707         {PRINT_VLP, "vlp"},
708 #endif /* DEVELOPER */
709         {-1, NULL}
710 };
711
712 static const struct enum_list enum_ldap_sasl_wrapping[] = {
713         {0, "plain"},
714         {ADS_AUTH_SASL_SIGN, "sign"},
715         {ADS_AUTH_SASL_SEAL, "seal"},
716         {-1, NULL}
717 };
718
719 static const struct enum_list enum_ldap_ssl[] = {
720         {LDAP_SSL_OFF, "no"},
721         {LDAP_SSL_OFF, "No"},
722         {LDAP_SSL_OFF, "off"},
723         {LDAP_SSL_OFF, "Off"},
724         {LDAP_SSL_START_TLS, "start tls"},
725         {LDAP_SSL_START_TLS, "Start_tls"},
726         {-1, NULL}
727 };
728
729 static const struct enum_list enum_ldap_passwd_sync[] = {
730         {LDAP_PASSWD_SYNC_OFF, "no"},
731         {LDAP_PASSWD_SYNC_OFF, "No"},
732         {LDAP_PASSWD_SYNC_OFF, "off"},
733         {LDAP_PASSWD_SYNC_OFF, "Off"},
734         {LDAP_PASSWD_SYNC_ON, "Yes"},
735         {LDAP_PASSWD_SYNC_ON, "yes"},
736         {LDAP_PASSWD_SYNC_ON, "on"},
737         {LDAP_PASSWD_SYNC_ON, "On"},
738         {LDAP_PASSWD_SYNC_ONLY, "Only"},
739         {LDAP_PASSWD_SYNC_ONLY, "only"},
740         {-1, NULL}
741 };
742
743 /* Types of machine we can announce as. */
744 #define ANNOUNCE_AS_NT_SERVER 1
745 #define ANNOUNCE_AS_WIN95 2
746 #define ANNOUNCE_AS_WFW 3
747 #define ANNOUNCE_AS_NT_WORKSTATION 4
748
749 static const struct enum_list enum_announce_as[] = {
750         {ANNOUNCE_AS_NT_SERVER, "NT"},
751         {ANNOUNCE_AS_NT_SERVER, "NT Server"},
752         {ANNOUNCE_AS_NT_WORKSTATION, "NT Workstation"},
753         {ANNOUNCE_AS_WIN95, "win95"},
754         {ANNOUNCE_AS_WFW, "WfW"},
755         {-1, NULL}
756 };
757
758 static const struct enum_list enum_map_readonly[] = {
759         {MAP_READONLY_NO, "no"},
760         {MAP_READONLY_NO, "false"},
761         {MAP_READONLY_NO, "0"},
762         {MAP_READONLY_YES, "yes"},
763         {MAP_READONLY_YES, "true"},
764         {MAP_READONLY_YES, "1"},
765         {MAP_READONLY_PERMISSIONS, "permissions"},
766         {MAP_READONLY_PERMISSIONS, "perms"},
767         {-1, NULL}
768 };
769
770 static const struct enum_list enum_case[] = {
771         {CASE_LOWER, "lower"},
772         {CASE_UPPER, "upper"},
773         {-1, NULL}
774 };
775
776 static const struct enum_list enum_bool_auto[] = {
777         {False, "No"},
778         {False, "False"},
779         {False, "0"},
780         {True, "Yes"},
781         {True, "True"},
782         {True, "1"},
783         {Auto, "Auto"},
784         {-1, NULL}
785 };
786
787 /* Client-side offline caching policy types */
788 #define CSC_POLICY_MANUAL 0
789 #define CSC_POLICY_DOCUMENTS 1
790 #define CSC_POLICY_PROGRAMS 2
791 #define CSC_POLICY_DISABLE 3
792
793 static const struct enum_list enum_csc_policy[] = {
794         {CSC_POLICY_MANUAL, "manual"},
795         {CSC_POLICY_DOCUMENTS, "documents"},
796         {CSC_POLICY_PROGRAMS, "programs"},
797         {CSC_POLICY_DISABLE, "disable"},
798         {-1, NULL}
799 };
800
801 /* SMB signing types. */
802 static const struct enum_list enum_smb_signing_vals[] = {
803         {False, "No"},
804         {False, "False"},
805         {False, "0"},
806         {False, "Off"},
807         {False, "disabled"},
808         {True, "Yes"},
809         {True, "True"},
810         {True, "1"},
811         {True, "On"},
812         {True, "enabled"},
813         {Auto, "auto"},
814         {Required, "required"},
815         {Required, "mandatory"},
816         {Required, "force"},
817         {Required, "forced"},
818         {Required, "enforced"},
819         {-1, NULL}
820 };
821
822 /* ACL compatibility options. */
823 static const struct enum_list enum_acl_compat_vals[] = {
824     { ACL_COMPAT_AUTO, "auto" },
825     { ACL_COMPAT_WINNT, "winnt" },
826     { ACL_COMPAT_WIN2K, "win2k" },
827     { -1, NULL}
828 };
829
830 /* 
831    Do you want session setups at user level security with a invalid
832    password to be rejected or allowed in as guest? WinNT rejects them
833    but it can be a pain as it means "net view" needs to use a password
834
835    You have 3 choices in the setting of map_to_guest:
836
837    "Never" means session setups with an invalid password
838    are rejected. This is the default.
839
840    "Bad User" means session setups with an invalid password
841    are rejected, unless the username does not exist, in which case it
842    is treated as a guest login
843
844    "Bad Password" means session setups with an invalid password
845    are treated as a guest login
846
847    Note that map_to_guest only has an effect in user or server
848    level security.
849 */
850
851 static const struct enum_list enum_map_to_guest[] = {
852         {NEVER_MAP_TO_GUEST, "Never"},
853         {MAP_TO_GUEST_ON_BAD_USER, "Bad User"},
854         {MAP_TO_GUEST_ON_BAD_PASSWORD, "Bad Password"},
855         {MAP_TO_GUEST_ON_BAD_UID, "Bad Uid"},
856         {-1, NULL}
857 };
858
859 /* Config backend options */
860
861 static const struct enum_list enum_config_backend[] = {
862         {CONFIG_BACKEND_FILE, "file"},
863         {CONFIG_BACKEND_REGISTRY, "registry"},
864         {-1, NULL}
865 };
866
867 /* Note: We do not initialise the defaults union - it is not allowed in ANSI C
868  *
869  * The FLAG_HIDE is explicit. Paramters set this way do NOT appear in any edit
870  * screen in SWAT. This is used to exclude parameters as well as to squash all
871  * parameters that have been duplicated by pseudonyms.
872  *
873  * NOTE: To display a parameter in BASIC view set FLAG_BASIC
874  *       Any parameter that does NOT have FLAG_ADVANCED will not disply at all
875  *       Set FLAG_SHARE and FLAG_PRINT to specifically display parameters in
876  *        respective views.
877  *
878  * NOTE2: Handling of duplicated (synonym) paramters:
879  *      Only the first occurance of a parameter should be enabled by FLAG_BASIC
880  *      and/or FLAG_ADVANCED. All duplicates following the first mention should be
881  *      set to FLAG_HIDE. ie: Make you must place the parameter that has the preferred
882  *      name first, and all synonyms must follow it with the FLAG_HIDE attribute.
883  */
884
885 static struct parm_struct parm_table[] = {
886         {N_("Base Options"), P_SEP, P_SEPARATOR},
887
888         {
889                 .label          = "dos charset",
890                 .type           = P_STRING,
891                 .p_class        = P_GLOBAL,
892                 .ptr            = &Globals.dos_charset,
893                 .special        = handle_charset,
894                 .enum_list      = NULL,
895                 .flags          = FLAG_ADVANCED
896         },
897         {
898                 .label          = "unix charset",
899                 .type           = P_STRING,
900                 .p_class        = P_GLOBAL,
901                 .ptr            = &Globals.unix_charset,
902                 .special        = handle_charset,
903                 .enum_list      = NULL,
904                 .flags          = FLAG_ADVANCED
905         },
906         {
907                 .label          = "display charset",
908                 .type           = P_STRING,
909                 .p_class        = P_GLOBAL,
910                 .ptr            = &Globals.display_charset,
911                 .special        = handle_charset,
912                 .enum_list      = NULL,
913                 .flags          = FLAG_ADVANCED
914         },
915         {
916                 .label          = "comment",
917                 .type           = P_STRING,
918                 .p_class        = P_LOCAL,
919                 .ptr            = &sDefault.comment,
920                 .special        = NULL,
921                 .enum_list      = NULL,
922                 .flags          = FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT
923         },
924         {
925                 .label          = "path",
926                 .type           = P_STRING,
927                 .p_class        = P_LOCAL,
928                 .ptr            = &sDefault.szPath,
929                 .special        = NULL,
930                 .enum_list      = NULL,
931                 .flags          = FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT,
932         },
933         {
934                 .label          = "directory",
935                 .type           = P_STRING,
936                 .p_class        = P_LOCAL,
937                 .ptr            = &sDefault.szPath,
938                 .special        = NULL,
939                 .enum_list      = NULL,
940                 .flags          = FLAG_HIDE,
941         },
942         {
943                 .label          = "workgroup",
944                 .type           = P_USTRING,
945                 .p_class        = P_GLOBAL,
946                 .ptr            = &Globals.szWorkgroup,
947                 .special        = handle_workgroup,
948                 .enum_list      = NULL,
949                 .flags          = FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD,
950         },
951 #ifdef WITH_ADS
952         {
953                 .label          = "realm",
954                 .type           = P_USTRING,
955                 .p_class        = P_GLOBAL,
956                 .ptr            = &Globals.szRealm,
957                 .special        = NULL,
958                 .enum_list      = NULL,
959                 .flags          = FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD,
960         },
961 #endif
962         {
963                 .label          = "netbios name",
964                 .type           = P_USTRING,
965                 .p_class        = P_GLOBAL,
966                 .ptr            = &Globals.szNetbiosName,
967                 .special        = handle_netbios_name,
968                 .enum_list      = NULL,
969                 .flags          = FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD,
970         },
971         {
972                 .label          = "netbios aliases",
973                 .type           = P_LIST,
974                 .p_class        = P_GLOBAL,
975                 .ptr            = &Globals.szNetbiosAliases,
976                 .special        = handle_netbios_aliases,
977                 .enum_list      = NULL,
978                 .flags          = FLAG_ADVANCED,
979         },
980         {
981                 .label          = "netbios scope",
982                 .type           = P_USTRING,
983                 .p_class        = P_GLOBAL,
984                 .ptr            = &Globals.szNetbiosScope,
985                 .special        = handle_netbios_scope,
986                 .enum_list      = NULL,
987                 .flags          = FLAG_ADVANCED,
988         },
989         {
990                 .label          = "server string",
991                 .type           = P_STRING,
992                 .p_class        = P_GLOBAL,
993                 .ptr            = &Globals.szServerString,
994                 .special        = NULL,
995                 .enum_list      = NULL,
996                 .flags          = FLAG_BASIC | FLAG_ADVANCED,
997         },
998         {
999                 .label          = "interfaces",
1000                 .type           = P_LIST,
1001                 .p_class        = P_GLOBAL,
1002                 .ptr            = &Globals.szInterfaces,
1003                 .special        = NULL,
1004                 .enum_list      = NULL,
1005                 .flags          = FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD,
1006         },
1007         {
1008                 .label          = "bind interfaces only",
1009                 .type           = P_BOOL,
1010                 .p_class        = P_GLOBAL,
1011                 .ptr            = &Globals.bBindInterfacesOnly,
1012                 .special        = NULL,
1013                 .enum_list      = NULL,
1014                 .flags          = FLAG_ADVANCED | FLAG_WIZARD,
1015         },
1016         {
1017                 .label          = "config backend",
1018                 .type           = P_ENUM,
1019                 .p_class        = P_GLOBAL,
1020                 .ptr            = &Globals.ConfigBackend,
1021                 .special        = NULL,
1022                 .enum_list      = enum_config_backend,
1023                 .flags          = FLAG_ADVANCED,
1024         },
1025
1026         {N_("Security Options"), P_SEP, P_SEPARATOR},
1027
1028         {
1029                 .label          = "security",
1030                 .type           = P_ENUM,
1031                 .p_class        = P_GLOBAL,
1032                 .ptr            = &Globals.security,
1033                 .special        = NULL,
1034                 .enum_list      = enum_security,
1035                 .flags          = FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD,
1036         },
1037         {
1038                 .label          = "auth methods",
1039                 .type           = P_LIST,
1040                 .p_class        = P_GLOBAL,
1041                 .ptr            = &Globals.AuthMethods,
1042                 .special        = NULL,
1043                 .enum_list      = NULL,
1044                 .flags          = FLAG_ADVANCED,
1045         },
1046         {
1047                 .label          = "encrypt passwords",
1048                 .type           = P_BOOL,
1049                 .p_class        = P_GLOBAL,
1050                 .ptr            = &Globals.bEncryptPasswords,
1051                 .special        = NULL,
1052                 .enum_list      = NULL,
1053                 .flags          = FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD,
1054         },
1055         {
1056                 .label          = "update encrypted",
1057                 .type           = P_BOOL,
1058                 .p_class        = P_GLOBAL,
1059                 .ptr            = &Globals.bUpdateEncrypt,
1060                 .special        = NULL,
1061                 .enum_list      = NULL,
1062                 .flags          = FLAG_ADVANCED,
1063         },
1064         {
1065                 .label          = "client schannel",
1066                 .type           = P_ENUM,
1067                 .p_class        = P_GLOBAL,
1068                 .ptr            = &Globals.clientSchannel,
1069                 .special        = NULL,
1070                 .enum_list      = enum_bool_auto,
1071                 .flags          = FLAG_BASIC | FLAG_ADVANCED,
1072         },
1073         {
1074                 .label          = "server schannel",
1075                 .type           = P_ENUM,
1076                 .p_class        = P_GLOBAL,
1077                 .ptr            = &Globals.serverSchannel,
1078                 .special        = NULL,
1079                 .enum_list      = enum_bool_auto,
1080                 .flags          = FLAG_BASIC | FLAG_ADVANCED,
1081         },
1082         {
1083                 .label          = "allow trusted domains",
1084                 .type           = P_BOOL,
1085                 .p_class        = P_GLOBAL,
1086                 .ptr            = &Globals.bAllowTrustedDomains,
1087                 .special        = NULL,
1088                 .enum_list      = NULL,
1089                 .flags          = FLAG_ADVANCED,
1090         },
1091         {
1092                 .label          = "map to guest",
1093                 .type           = P_ENUM,
1094                 .p_class        = P_GLOBAL,
1095                 .ptr            = &Globals.map_to_guest,
1096                 .special        = NULL,
1097                 .enum_list      = enum_map_to_guest,
1098                 .flags          = FLAG_ADVANCED,
1099         },
1100         {
1101                 .label          = "null passwords",
1102                 .type           = P_BOOL,
1103                 .p_class        = P_GLOBAL,
1104                 .ptr            = &Globals.bNullPasswords,
1105                 .special        = NULL,
1106                 .enum_list      = NULL,
1107                 .flags          = FLAG_ADVANCED,
1108         },
1109         {
1110                 .label          = "obey pam restrictions",
1111                 .type           = P_BOOL,
1112                 .p_class        = P_GLOBAL,
1113                 .ptr            = &Globals.bObeyPamRestrictions,
1114                 .special        = NULL,
1115                 .enum_list      = NULL,
1116                 .flags          = FLAG_ADVANCED,
1117         },
1118         {
1119                 .label          = "password server",
1120                 .type           = P_STRING,
1121                 .p_class        = P_GLOBAL,
1122                 .ptr            = &Globals.szPasswordServer,
1123                 .special        = NULL,
1124                 .enum_list      = NULL,
1125                 .flags          = FLAG_ADVANCED | FLAG_WIZARD,
1126         },
1127         {
1128                 .label          = "smb passwd file",
1129                 .type           = P_STRING,
1130                 .p_class        = P_GLOBAL,
1131                 .ptr            = &Globals.szSMBPasswdFile,
1132                 .special        = NULL,
1133                 .enum_list      = NULL,
1134                 .flags          = FLAG_ADVANCED,
1135         },
1136         {
1137                 .label          = "private dir",
1138                 .type           = P_STRING,
1139                 .p_class        = P_GLOBAL,
1140                 .ptr            = &Globals.szPrivateDir,
1141                 .special        = NULL,
1142                 .enum_list      = NULL,
1143                 .flags          = FLAG_ADVANCED,
1144         },
1145         {
1146                 .label          = "passdb backend",
1147                 .type           = P_STRING,
1148                 .p_class        = P_GLOBAL,
1149                 .ptr            = &Globals.szPassdbBackend,
1150                 .special        = NULL,
1151                 .enum_list      = NULL,
1152                 .flags          = FLAG_ADVANCED | FLAG_WIZARD,
1153         },
1154         {
1155                 .label          = "algorithmic rid base",
1156                 .type           = P_INTEGER,
1157                 .p_class        = P_GLOBAL,
1158                 .ptr            = &Globals.AlgorithmicRidBase,
1159                 .special        = NULL,
1160                 .enum_list      = NULL,
1161                 .flags          = FLAG_ADVANCED,
1162         },
1163         {
1164                 .label          = "root directory",
1165                 .type           = P_STRING,
1166                 .p_class        = P_GLOBAL,
1167                 .ptr            = &Globals.szRootdir,
1168                 .special        = NULL,
1169                 .enum_list      = NULL,
1170                 .flags          = FLAG_ADVANCED,
1171         },
1172         {
1173                 .label          = "root dir",
1174                 .type           = P_STRING,
1175                 .p_class        = P_GLOBAL,
1176                 .ptr            = &Globals.szRootdir,
1177                 .special        = NULL,
1178                 .enum_list      = NULL,
1179                 .flags          = FLAG_HIDE,
1180         },
1181         {
1182                 .label          = "root",
1183                 .type           = P_STRING,
1184                 .p_class        = P_GLOBAL,
1185                 .ptr            = &Globals.szRootdir,
1186                 .special        = NULL,
1187                 .enum_list      = NULL,
1188                 .flags          = FLAG_HIDE,
1189         },
1190         {
1191                 .label          = "guest account",
1192                 .type           = P_STRING,
1193                 .p_class        = P_GLOBAL,
1194                 .ptr            = &Globals.szGuestaccount,
1195                 .special        = NULL,
1196                 .enum_list      = NULL,
1197                 .flags          = FLAG_BASIC | FLAG_ADVANCED,
1198         },
1199         {
1200                 .label          = "enable privileges",
1201                 .type           = P_BOOL,
1202                 .p_class        = P_GLOBAL,
1203                 .ptr            = &Globals.bEnablePrivileges,
1204                 .special        = NULL,
1205                 .enum_list      = NULL,
1206                 .flags          = FLAG_ADVANCED,
1207         },
1208
1209         {
1210                 .label          = "pam password change",
1211                 .type           = P_BOOL,
1212                 .p_class        = P_GLOBAL,
1213                 .ptr            = &Globals.bPamPasswordChange,
1214                 .special        = NULL,
1215                 .enum_list      = NULL,
1216                 .flags          = FLAG_ADVANCED,
1217         },
1218         {
1219                 .label          = "passwd program",
1220                 .type           = P_STRING,
1221                 .p_class        = P_GLOBAL,
1222                 .ptr            = &Globals.szPasswdProgram,
1223                 .special        = NULL,
1224                 .enum_list      = NULL,
1225                 .flags          = FLAG_ADVANCED,
1226         },
1227         {
1228                 .label          = "passwd chat",
1229                 .type           = P_STRING,
1230                 .p_class        = P_GLOBAL,
1231                 .ptr            = &Globals.szPasswdChat,
1232                 .special        = NULL,
1233                 .enum_list      = NULL,
1234                 .flags          = FLAG_ADVANCED,
1235         },
1236         {
1237                 .label          = "passwd chat debug",
1238                 .type           = P_BOOL,
1239                 .p_class        = P_GLOBAL,
1240                 .ptr            = &Globals.bPasswdChatDebug,
1241                 .special        = NULL,
1242                 .enum_list      = NULL,
1243                 .flags          = FLAG_ADVANCED,
1244         },
1245         {
1246                 .label          = "passwd chat timeout",
1247                 .type           = P_INTEGER,
1248                 .p_class        = P_GLOBAL,
1249                 .ptr            = &Globals.iPasswdChatTimeout,
1250                 .special        = NULL,
1251                 .enum_list      = NULL,
1252                 .flags          = FLAG_ADVANCED,
1253         },
1254         {
1255                 .label          = "check password script",
1256                 .type           = P_STRING,
1257                 .p_class        = P_GLOBAL,
1258                 .ptr            = &Globals.szCheckPasswordScript,
1259                 .special        = NULL,
1260                 .enum_list      = NULL,
1261                 .flags          = FLAG_ADVANCED,
1262         },
1263         {
1264                 .label          = "username map",
1265                 .type           = P_STRING,
1266                 .p_class        = P_GLOBAL,
1267                 .ptr            = &Globals.szUsernameMap,
1268                 .special        = NULL,
1269                 .enum_list      = NULL,
1270                 .flags          = FLAG_ADVANCED,
1271         },
1272         {
1273                 .label          = "password level",
1274                 .type           = P_INTEGER,
1275                 .p_class        = P_GLOBAL,
1276                 .ptr            = &Globals.pwordlevel,
1277                 .special        = NULL,
1278                 .enum_list      = NULL,
1279                 .flags          = FLAG_ADVANCED,
1280         },
1281         {
1282                 .label          = "username level",
1283                 .type           = P_INTEGER,
1284                 .p_class        = P_GLOBAL,
1285                 .ptr            = &Globals.unamelevel,
1286                 .special        = NULL,
1287                 .enum_list      = NULL,
1288                 .flags          = FLAG_ADVANCED,
1289         },
1290         {
1291                 .label          = "unix password sync",
1292                 .type           = P_BOOL,
1293                 .p_class        = P_GLOBAL,
1294                 .ptr            = &Globals.bUnixPasswdSync,
1295                 .special        = NULL,
1296                 .enum_list      = NULL,
1297                 .flags          = FLAG_ADVANCED,
1298         },
1299         {
1300                 .label          = "restrict anonymous",
1301                 .type           = P_INTEGER,
1302                 .p_class        = P_GLOBAL,
1303                 .ptr            = &Globals.restrict_anonymous,
1304                 .special        = NULL,
1305                 .enum_list      = NULL,
1306                 .flags          = FLAG_ADVANCED,
1307         },
1308         {
1309                 .label          = "lanman auth",
1310                 .type           = P_BOOL,
1311                 .p_class        = P_GLOBAL,
1312                 .ptr            = &Globals.bLanmanAuth,
1313                 .special        = NULL,
1314                 .enum_list      = NULL,
1315                 .flags          = FLAG_ADVANCED,
1316         },
1317         {
1318                 .label          = "ntlm auth",
1319                 .type           = P_BOOL,
1320                 .p_class        = P_GLOBAL,
1321                 .ptr            = &Globals.bNTLMAuth,
1322                 .special        = NULL,
1323                 .enum_list      = NULL,
1324                 .flags          = FLAG_ADVANCED,
1325         },
1326         {
1327                 .label          = "client NTLMv2 auth",
1328                 .type           = P_BOOL,
1329                 .p_class        = P_GLOBAL,
1330                 .ptr            = &Globals.bClientNTLMv2Auth,
1331                 .special        = NULL,
1332                 .enum_list      = NULL,
1333                 .flags          = FLAG_ADVANCED,
1334         },
1335         {
1336                 .label          = "client lanman auth",
1337                 .type           = P_BOOL,
1338                 .p_class        = P_GLOBAL,
1339                 .ptr            = &Globals.bClientLanManAuth,
1340                 .special        = NULL,
1341                 .enum_list      = NULL,
1342                 .flags          = FLAG_ADVANCED,
1343         },
1344         {
1345                 .label          = "client plaintext auth",
1346                 .type           = P_BOOL,
1347                 .p_class        = P_GLOBAL,
1348                 .ptr            = &Globals.bClientPlaintextAuth,
1349                 .special        = NULL,
1350                 .enum_list      = NULL,
1351                 .flags          = FLAG_ADVANCED,
1352         },
1353         {
1354                 .label          = "username",
1355                 .type           = P_STRING,
1356                 .p_class        = P_LOCAL,
1357                 .ptr            = &sDefault.szUsername,
1358                 .special        = NULL,
1359                 .enum_list      = NULL,
1360                 .flags          = FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE,
1361         },
1362         {
1363                 .label          = "user",
1364                 .type           = P_STRING,
1365                 .p_class        = P_LOCAL,
1366                 .ptr            = &sDefault.szUsername,
1367                 .special        = NULL,
1368                 .enum_list      = NULL,
1369                 .flags          = FLAG_HIDE,
1370         },
1371         {
1372                 .label          = "users",
1373                 .type           = P_STRING,
1374                 .p_class        = P_LOCAL,
1375                 .ptr            = &sDefault.szUsername,
1376                 .special        = NULL,
1377                 .enum_list      = NULL,
1378                 .flags          = FLAG_HIDE,
1379         },
1380         {
1381                 .label          = "invalid users",
1382                 .type           = P_LIST,
1383                 .p_class        = P_LOCAL,
1384                 .ptr            = &sDefault.szInvalidUsers,
1385                 .special        = NULL,
1386                 .enum_list      = NULL,
1387                 .flags          = FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE,
1388         },
1389         {
1390                 .label          = "valid users",
1391                 .type           = P_LIST,
1392                 .p_class        = P_LOCAL,
1393                 .ptr            = &sDefault.szValidUsers,
1394                 .special        = NULL,
1395                 .enum_list      = NULL,
1396                 .flags          = FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE,
1397         },
1398         {
1399                 .label          = "admin users",
1400                 .type           = P_LIST,
1401                 .p_class        = P_LOCAL,
1402                 .ptr            = &sDefault.szAdminUsers,
1403                 .special        = NULL,
1404                 .enum_list      = NULL,
1405                 .flags          = FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE,
1406         },
1407         {
1408                 .label          = "read list",
1409                 .type           = P_LIST,
1410                 .p_class        = P_LOCAL,
1411                 .ptr            = &sDefault.readlist,
1412                 .special        = NULL,
1413                 .enum_list      = NULL,
1414                 .flags          = FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE,
1415         },
1416         {
1417                 .label          = "write list",
1418                 .type           = P_LIST,
1419                 .p_class        = P_LOCAL,
1420                 .ptr            = &sDefault.writelist,
1421                 .special        = NULL,
1422                 .enum_list      = NULL,
1423                 .flags          = FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE,
1424         },
1425         {
1426                 .label          = "printer admin",
1427                 .type           = P_LIST,
1428                 .p_class        = P_LOCAL,
1429                 .ptr            = &sDefault.printer_admin,
1430                 .special        = NULL,
1431                 .enum_list      = NULL,
1432                 .flags          = FLAG_ADVANCED | FLAG_GLOBAL | FLAG_PRINT | FLAG_DEPRECATED,
1433         },
1434         {
1435                 .label          = "force user",
1436                 .type           = P_STRING,
1437                 .p_class        = P_LOCAL,
1438                 .ptr            = &sDefault.force_user,
1439                 .special        = NULL,
1440                 .enum_list      = NULL,
1441                 .flags          = FLAG_ADVANCED | FLAG_SHARE,
1442         },
1443         {
1444                 .label          = "force group",
1445                 .type           = P_STRING,
1446                 .p_class        = P_LOCAL,
1447                 .ptr            = &sDefault.force_group,
1448                 .special        = NULL,
1449                 .enum_list      = NULL,
1450                 .flags          = FLAG_ADVANCED | FLAG_SHARE,
1451         },
1452         {
1453                 .label          = "group",
1454                 .type           = P_STRING,
1455                 .p_class        = P_LOCAL,
1456                 .ptr            = &sDefault.force_group,
1457                 .special        = NULL,
1458                 .enum_list      = NULL,
1459                 .flags          = FLAG_ADVANCED,
1460         },
1461         {
1462                 .label          = "read only",
1463                 .type           = P_BOOL,
1464                 .p_class        = P_LOCAL,
1465                 .ptr            = &sDefault.bRead_only,
1466                 .special        = NULL,
1467                 .enum_list      = NULL,
1468                 .flags          = FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE,
1469         },
1470         {
1471                 .label          = "write ok",
1472                 .type           = P_BOOLREV,
1473                 .p_class        = P_LOCAL,
1474                 .ptr            = &sDefault.bRead_only,
1475                 .special        = NULL,
1476                 .enum_list      = NULL,
1477                 .flags          = FLAG_HIDE,
1478         },
1479         {
1480                 .label          = "writeable",
1481                 .type           = P_BOOLREV,
1482                 .p_class        = P_LOCAL,
1483                 .ptr            = &sDefault.bRead_only,
1484                 .special        = NULL,
1485                 .enum_list      = NULL,
1486                 .flags          = FLAG_HIDE,
1487         },
1488         {
1489                 .label          = "writable",
1490                 .type           = P_BOOLREV,
1491                 .p_class        = P_LOCAL,
1492                 .ptr            = &sDefault.bRead_only,
1493                 .special        = NULL,
1494                 .enum_list      = NULL,
1495                 .flags          = FLAG_HIDE,
1496         },
1497         {
1498                 .label          = "acl check permissions",
1499                 .type           = P_BOOL,
1500                 .p_class        = P_LOCAL,
1501                 .ptr            = &sDefault.bAclCheckPermissions,
1502                 .special        = NULL,
1503                 .enum_list      = NULL,
1504                 .flags          = FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE,
1505         },
1506         {
1507                 .label          = "acl group control",
1508                 .type           = P_BOOL,
1509                 .p_class        = P_LOCAL,
1510                 .ptr            = &sDefault.bAclGroupControl,
1511                 .special        = NULL,
1512                 .enum_list      = NULL,
1513                 .flags          = FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE,
1514         },
1515         {
1516                 .label          = "acl map full control",
1517                 .type           = P_BOOL,
1518                 .p_class        = P_LOCAL,
1519                 .ptr            = &sDefault.bAclMapFullControl,
1520                 .special        = NULL,
1521                 .enum_list      = NULL,
1522                 .flags          = FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE,
1523         },
1524         {
1525                 .label          = "create mask",
1526                 .type           = P_OCTAL,
1527                 .p_class        = P_LOCAL,
1528                 .ptr            = &sDefault.iCreate_mask,
1529                 .special        = NULL,
1530                 .enum_list      = NULL,
1531                 .flags          = FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE,
1532         },
1533         {
1534                 .label          = "create mode",
1535                 .type           = P_OCTAL,
1536                 .p_class        = P_LOCAL,
1537                 .ptr            = &sDefault.iCreate_mask,
1538                 .special        = NULL,
1539                 .enum_list      = NULL,
1540                 .flags          = FLAG_HIDE,
1541         },
1542         {
1543                 .label          = "force create mode",
1544                 .type           = P_OCTAL,
1545                 .p_class        = P_LOCAL,
1546                 .ptr            = &sDefault.iCreate_force_mode,
1547                 .special        = NULL,
1548                 .enum_list      = NULL,
1549                 .flags          = FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE,
1550         },
1551         {
1552                 .label          = "security mask",
1553                 .type           = P_OCTAL,
1554                 .p_class        = P_LOCAL,
1555                 .ptr            = &sDefault.iSecurity_mask,
1556                 .special        = NULL,
1557                 .enum_list      = NULL,
1558                 .flags          = FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE,
1559         },
1560         {
1561                 .label          = "force security mode",
1562                 .type           = P_OCTAL,
1563                 .p_class        = P_LOCAL,
1564                 .ptr            = &sDefault.iSecurity_force_mode,
1565                 .special        = NULL,
1566                 .enum_list      = NULL,
1567                 .flags          = FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE,
1568         },
1569         {
1570                 .label          = "directory mask",
1571                 .type           = P_OCTAL,
1572                 .p_class        = P_LOCAL,
1573                 .ptr            = &sDefault.iDir_mask,
1574                 .special        = NULL,
1575                 .enum_list      = NULL,
1576                 .flags          = FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE,
1577         },
1578         {
1579                 .label          = "directory mode",
1580                 .type           = P_OCTAL,
1581                 .p_class        = P_LOCAL,
1582                 .ptr            = &sDefault.iDir_mask,
1583                 .special        = NULL,
1584                 .enum_list      = NULL,
1585                 .flags          = FLAG_ADVANCED | FLAG_GLOBAL,
1586         },
1587         {
1588                 .label          = "force directory mode",
1589                 .type           = P_OCTAL,
1590                 .p_class        = P_LOCAL,
1591                 .ptr            = &sDefault.iDir_force_mode,
1592                 .special        = NULL,
1593                 .enum_list      = NULL,
1594                 .flags          = FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE,
1595         },
1596         {
1597                 .label          = "directory security mask",
1598                 .type           = P_OCTAL,
1599                 .p_class        = P_LOCAL,
1600                 .ptr            = &sDefault.iDir_Security_mask,
1601                 .special        = NULL,
1602                 .enum_list      = NULL,
1603                 .flags          = FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE,
1604         },
1605         {
1606                 .label          = "force directory security mode",
1607                 .type           = P_OCTAL,
1608                 .p_class        = P_LOCAL,
1609                 .ptr            = &sDefault.iDir_Security_force_mode,
1610                 .special        = NULL,
1611                 .enum_list      = NULL,
1612                 .flags          = FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE,
1613         },
1614         {
1615                 .label          = "force unknown acl user",
1616                 .type           = P_BOOL,
1617                 .p_class        = P_LOCAL,
1618                 .ptr            = &sDefault.bForceUnknownAclUser,
1619                 .special        = NULL,
1620                 .enum_list      = NULL,
1621                 .flags          = FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE,
1622         },
1623         {
1624                 .label          = "inherit permissions",
1625                 .type           = P_BOOL,
1626                 .p_class        = P_LOCAL,
1627                 .ptr            = &sDefault.bInheritPerms,
1628                 .special        = NULL,
1629                 .enum_list      = NULL,
1630                 .flags          = FLAG_ADVANCED | FLAG_SHARE,
1631         },
1632         {
1633                 .label          = "inherit acls",
1634                 .type           = P_BOOL,
1635                 .p_class        = P_LOCAL,
1636                 .ptr            = &sDefault.bInheritACLS,
1637                 .special        = NULL,
1638                 .enum_list      = NULL,
1639                 .flags          = FLAG_ADVANCED | FLAG_SHARE,
1640         },
1641         {
1642                 .label          = "inherit owner",
1643                 .type           = P_BOOL,
1644                 .p_class        = P_LOCAL,
1645                 .ptr            = &sDefault.bInheritOwner,
1646                 .special        = NULL,
1647                 .enum_list      = NULL,
1648                 .flags          = FLAG_ADVANCED | FLAG_SHARE,
1649         },
1650         {
1651                 .label          = "guest only",
1652                 .type           = P_BOOL,
1653                 .p_class        = P_LOCAL,
1654                 .ptr            = &sDefault.bGuest_only,
1655                 .special        = NULL,
1656                 .enum_list      = NULL,
1657                 .flags          = FLAG_ADVANCED | FLAG_SHARE,
1658         },
1659         {
1660                 .label          = "only guest",
1661                 .type           = P_BOOL,
1662                 .p_class        = P_LOCAL,
1663                 .ptr            = &sDefault.bGuest_only,
1664                 .special        = NULL,
1665                 .enum_list      = NULL,
1666                 .flags          = FLAG_HIDE,
1667         },
1668         {
1669                 .label          = "administrative share",
1670                 .type           = P_BOOL,
1671                 .p_class        = P_LOCAL,
1672                 .ptr            = &sDefault.bAdministrative_share,
1673                 .special        = NULL,
1674                 .enum_list      = NULL,
1675                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT,
1676         },
1677
1678         {
1679                 .label          = "guest ok",
1680                 .type           = P_BOOL,
1681                 .p_class        = P_LOCAL,
1682                 .ptr            = &sDefault.bGuest_ok,
1683                 .special        = NULL,
1684                 .enum_list      = NULL,
1685                 .flags          = FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT,
1686         },
1687         {
1688                 .label          = "public",
1689                 .type           = P_BOOL,
1690                 .p_class        = P_LOCAL,
1691                 .ptr            = &sDefault.bGuest_ok,
1692                 .special        = NULL,
1693                 .enum_list      = NULL,
1694                 .flags          = FLAG_HIDE,
1695         },
1696         {
1697                 .label          = "only user",
1698                 .type           = P_BOOL,
1699                 .p_class        = P_LOCAL,
1700                 .ptr            = &sDefault.bOnlyUser,
1701                 .special        = NULL,
1702                 .enum_list      = NULL,
1703                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_DEPRECATED,
1704         },
1705         {
1706                 .label          = "hosts allow",
1707                 .type           = P_LIST,
1708                 .p_class        = P_LOCAL,
1709                 .ptr            = &sDefault.szHostsallow,
1710                 .special        = NULL,
1711                 .enum_list      = NULL,
1712                 .flags          = FLAG_GLOBAL | FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT,
1713         },
1714         {
1715                 .label          = "allow hosts",
1716                 .type           = P_LIST,
1717                 .p_class        = P_LOCAL,
1718                 .ptr            = &sDefault.szHostsallow,
1719                 .special        = NULL,
1720                 .enum_list      = NULL,
1721                 .flags          = FLAG_HIDE,
1722         },
1723         {
1724                 .label          = "hosts deny",
1725                 .type           = P_LIST,
1726                 .p_class        = P_LOCAL,
1727                 .ptr            = &sDefault.szHostsdeny,
1728                 .special        = NULL,
1729                 .enum_list      = NULL,
1730                 .flags          = FLAG_GLOBAL | FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT,
1731         },
1732         {
1733                 .label          = "deny hosts",
1734                 .type           = P_LIST,
1735                 .p_class        = P_LOCAL,
1736                 .ptr            = &sDefault.szHostsdeny,
1737                 .special        = NULL,
1738                 .enum_list      = NULL,
1739                 .flags          = FLAG_HIDE,
1740         },
1741         {
1742                 .label          = "preload modules",
1743                 .type           = P_LIST,
1744                 .p_class        = P_GLOBAL,
1745                 .ptr            = &Globals.szPreloadModules,
1746                 .special        = NULL,
1747                 .enum_list      = NULL,
1748                 .flags          = FLAG_ADVANCED | FLAG_GLOBAL,
1749         },
1750         {
1751                 .label          = "use kerberos keytab",
1752                 .type           = P_BOOL,
1753                 .p_class        = P_GLOBAL,
1754                 .ptr            = &Globals.bUseKerberosKeytab,
1755                 .special        = NULL,
1756                 .enum_list      = NULL,
1757                 .flags          = FLAG_ADVANCED,
1758         },
1759
1760         {N_("Logging Options"), P_SEP, P_SEPARATOR},
1761
1762         {
1763                 .label          = "log level",
1764                 .type           = P_STRING,
1765                 .p_class        = P_GLOBAL,
1766                 .ptr            = &Globals.szLogLevel,
1767                 .special        = handle_debug_list,
1768                 .enum_list      = NULL,
1769                 .flags          = FLAG_ADVANCED,
1770         },
1771         {
1772                 .label          = "debuglevel",
1773                 .type           = P_STRING,
1774                 .p_class        = P_GLOBAL,
1775                 .ptr            = &Globals.szLogLevel,
1776                 .special        = handle_debug_list,
1777                 .enum_list      = NULL,
1778                 .flags          = FLAG_HIDE,
1779         },
1780         {
1781                 .label          = "syslog",
1782                 .type           = P_INTEGER,
1783                 .p_class        = P_GLOBAL,
1784                 .ptr            = &Globals.syslog,
1785                 .special        = NULL,
1786                 .enum_list      = NULL,
1787                 .flags          = FLAG_ADVANCED,
1788         },
1789         {
1790                 .label          = "syslog only",
1791                 .type           = P_BOOL,
1792                 .p_class        = P_GLOBAL,
1793                 .ptr            = &Globals.bSyslogOnly,
1794                 .special        = NULL,
1795                 .enum_list      = NULL,
1796                 .flags          = FLAG_ADVANCED,
1797         },
1798         {
1799                 .label          = "log file",
1800                 .type           = P_STRING,
1801                 .p_class        = P_GLOBAL,
1802                 .ptr            = &Globals.szLogFile,
1803                 .special        = NULL,
1804                 .enum_list      = NULL,
1805                 .flags          = FLAG_ADVANCED,
1806         },
1807         {
1808                 .label          = "max log size",
1809                 .type           = P_INTEGER,
1810                 .p_class        = P_GLOBAL,
1811                 .ptr            = &Globals.max_log_size,
1812                 .special        = NULL,
1813                 .enum_list      = NULL,
1814                 .flags          = FLAG_ADVANCED,
1815         },
1816         {
1817                 .label          = "debug timestamp",
1818                 .type           = P_BOOL,
1819                 .p_class        = P_GLOBAL,
1820                 .ptr            = &Globals.bTimestampLogs,
1821                 .special        = NULL,
1822                 .enum_list      = NULL,
1823                 .flags          = FLAG_ADVANCED,
1824         },
1825         {
1826                 .label          = "timestamp logs",
1827                 .type           = P_BOOL,
1828                 .p_class        = P_GLOBAL,
1829                 .ptr            = &Globals.bTimestampLogs,
1830                 .special        = NULL,
1831                 .enum_list      = NULL,
1832                 .flags          = FLAG_ADVANCED,
1833         },
1834         {
1835                 .label          = "debug prefix timestamp",
1836                 .type           = P_BOOL,
1837                 .p_class        = P_GLOBAL,
1838                 .ptr            = &Globals.bDebugPrefixTimestamp,
1839                 .special        = NULL,
1840                 .enum_list      = NULL,
1841                 .flags          = FLAG_ADVANCED,
1842         },
1843         {
1844                 .label          = "debug hires timestamp",
1845                 .type           = P_BOOL,
1846                 .p_class        = P_GLOBAL,
1847                 .ptr            = &Globals.bDebugHiresTimestamp,
1848                 .special        = NULL,
1849                 .enum_list      = NULL,
1850                 .flags          = FLAG_ADVANCED,
1851         },
1852         {
1853                 .label          = "debug pid",
1854                 .type           = P_BOOL,
1855                 .p_class        = P_GLOBAL,
1856                 .ptr            = &Globals.bDebugPid,
1857                 .special        = NULL,
1858                 .enum_list      = NULL,
1859                 .flags          = FLAG_ADVANCED,
1860         },
1861         {
1862                 .label          = "debug uid",
1863                 .type           = P_BOOL,
1864                 .p_class        = P_GLOBAL,
1865                 .ptr            = &Globals.bDebugUid,
1866                 .special        = NULL,
1867                 .enum_list      = NULL,
1868                 .flags          = FLAG_ADVANCED,
1869         },
1870         {
1871                 .label          = "debug class",
1872                 .type           = P_BOOL,
1873                 .p_class        = P_GLOBAL,
1874                 .ptr            = &Globals.bDebugClass,
1875                 .special        = NULL,
1876                 .enum_list      = NULL,
1877                 .flags          = FLAG_ADVANCED,
1878         },
1879         {
1880                 .label          = "enable core files",
1881                 .type           = P_BOOL,
1882                 .p_class        = P_GLOBAL,
1883                 .ptr            = &Globals.bEnableCoreFiles,
1884                 .special        = NULL,
1885                 .enum_list      = NULL,
1886                 .flags          = FLAG_ADVANCED,
1887         },
1888
1889         {N_("Protocol Options"), P_SEP, P_SEPARATOR},
1890
1891         {
1892                 .label          = "allocation roundup size",
1893                 .type           = P_INTEGER,
1894                 .p_class        = P_LOCAL,
1895                 .ptr            = &sDefault.iallocation_roundup_size,
1896                 .special        = NULL,
1897                 .enum_list      = NULL,
1898                 .flags          = FLAG_ADVANCED,
1899         },
1900         {
1901                 .label          = "aio read size",
1902                 .type           = P_INTEGER,
1903                 .p_class        = P_LOCAL,
1904                 .ptr            = &sDefault.iAioReadSize,
1905                 .special        = NULL,
1906                 .enum_list      = NULL,
1907                 .flags          = FLAG_ADVANCED,
1908         },
1909         {
1910                 .label          = "aio write size",
1911                 .type           = P_INTEGER,
1912                 .p_class        = P_LOCAL,
1913                 .ptr            = &sDefault.iAioWriteSize,
1914                 .special        = NULL,
1915                 .enum_list      = NULL,
1916                 .flags          = FLAG_ADVANCED,
1917         },
1918         {
1919                 .label          = "aio write behind",
1920                 .type           = P_STRING,
1921                 .p_class        = P_LOCAL,
1922                 .ptr            = &sDefault.szAioWriteBehind,
1923                 .special        = NULL,
1924                 .enum_list      = NULL,
1925                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
1926         },
1927         {
1928                 .label          = "smb ports",
1929                 .type           = P_STRING,
1930                 .p_class        = P_GLOBAL,
1931                 .ptr            = &Globals.smb_ports,
1932                 .special        = NULL,
1933                 .enum_list      = NULL,
1934                 .flags          = FLAG_ADVANCED,
1935         },
1936         {
1937                 .label          = "large readwrite",
1938                 .type           = P_BOOL,
1939                 .p_class        = P_GLOBAL,
1940                 .ptr            = &Globals.bLargeReadwrite,
1941                 .special        = NULL,
1942                 .enum_list      = NULL,
1943                 .flags          = FLAG_ADVANCED,
1944         },
1945         {
1946                 .label          = "max protocol",
1947                 .type           = P_ENUM,
1948                 .p_class        = P_GLOBAL,
1949                 .ptr            = &Globals.maxprotocol,
1950                 .special        = NULL,
1951                 .enum_list      = enum_protocol,
1952                 .flags          = FLAG_ADVANCED,
1953         },
1954         {
1955                 .label          = "protocol",
1956                 .type           = P_ENUM,
1957                 .p_class        = P_GLOBAL,
1958                 .ptr            = &Globals.maxprotocol,
1959                 .special        = NULL,
1960                 .enum_list      = enum_protocol,
1961                 .flags          = FLAG_ADVANCED,
1962         },
1963         {
1964                 .label          = "min protocol",
1965                 .type           = P_ENUM,
1966                 .p_class        = P_GLOBAL,
1967                 .ptr            = &Globals.minprotocol,
1968                 .special        = NULL,
1969                 .enum_list      = enum_protocol,
1970                 .flags          = FLAG_ADVANCED,
1971         },
1972         {
1973                 .label          = "min receivefile size",
1974                 .type           = P_INTEGER,
1975                 .p_class        = P_GLOBAL,
1976                 .ptr            = &Globals.iminreceivefile,
1977                 .special        = NULL,
1978                 .enum_list      = NULL,
1979                 .flags          = FLAG_ADVANCED,
1980         },
1981         {
1982                 .label          = "read raw",
1983                 .type           = P_BOOL,
1984                 .p_class        = P_GLOBAL,
1985                 .ptr            = &Globals.bReadRaw,
1986                 .special        = NULL,
1987                 .enum_list      = NULL,
1988                 .flags          = FLAG_ADVANCED,
1989         },
1990         {
1991                 .label          = "write raw",
1992                 .type           = P_BOOL,
1993                 .p_class        = P_GLOBAL,
1994                 .ptr            = &Globals.bWriteRaw,
1995                 .special        = NULL,
1996                 .enum_list      = NULL,
1997                 .flags          = FLAG_ADVANCED,
1998         },
1999         {
2000                 .label          = "disable netbios",
2001                 .type           = P_BOOL,
2002                 .p_class        = P_GLOBAL,
2003                 .ptr            = &Globals.bDisableNetbios,
2004                 .special        = NULL,
2005                 .enum_list      = NULL,
2006                 .flags          = FLAG_ADVANCED,
2007         },
2008         {
2009                 .label          = "reset on zero vc",
2010                 .type           = P_BOOL,
2011                 .p_class        = P_GLOBAL,
2012                 .ptr            = &Globals.bResetOnZeroVC,
2013                 .special        = NULL,
2014                 .enum_list      = NULL,
2015                 .flags          = FLAG_ADVANCED,
2016         },
2017         {
2018                 .label          = "acl compatibility",
2019                 .type           = P_ENUM,
2020                 .p_class        = P_GLOBAL,
2021                 .ptr            = &Globals.iAclCompat,
2022                 .special        = NULL,
2023                 .enum_list      = enum_acl_compat_vals,
2024                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
2025         },
2026         {
2027                 .label          = "defer sharing violations",
2028                 .type           = P_BOOL,
2029                 .p_class        = P_GLOBAL,
2030                 .ptr            = &Globals.bDeferSharingViolations,
2031                 .special        = NULL,
2032                 .enum_list      = NULL,
2033                 .flags          = FLAG_ADVANCED | FLAG_GLOBAL,
2034         },
2035         {
2036                 .label          = "ea support",
2037                 .type           = P_BOOL,
2038                 .p_class        = P_LOCAL,
2039                 .ptr            = &sDefault.bEASupport,
2040                 .special        = NULL,
2041                 .enum_list      = NULL,
2042                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
2043         },
2044         {
2045                 .label          = "nt acl support",
2046                 .type           = P_BOOL,
2047                 .p_class        = P_LOCAL,
2048                 .ptr            = &sDefault.bNTAclSupport,
2049                 .special        = NULL,
2050                 .enum_list      = NULL,
2051                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
2052         },
2053         {
2054                 .label          = "nt pipe support",
2055                 .type           = P_BOOL,
2056                 .p_class        = P_GLOBAL,
2057                 .ptr            = &Globals.bNTPipeSupport,
2058                 .special        = NULL,
2059                 .enum_list      = NULL,
2060                 .flags          = FLAG_ADVANCED,
2061         },
2062         {
2063                 .label          = "nt status support",
2064                 .type           = P_BOOL,
2065                 .p_class        = P_GLOBAL,
2066                 .ptr            = &Globals.bNTStatusSupport,
2067                 .special        = NULL,
2068                 .enum_list      = NULL,
2069                 .flags          = FLAG_ADVANCED,
2070         },
2071         {
2072                 .label          = "profile acls",
2073                 .type           = P_BOOL,
2074                 .p_class        = P_LOCAL,
2075                 .ptr            = &sDefault.bProfileAcls,
2076                 .special        = NULL,
2077                 .enum_list      = NULL,
2078                 .flags          = FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE,
2079         },
2080         {
2081                 .label          = "announce version",
2082                 .type           = P_STRING,
2083                 .p_class        = P_GLOBAL,
2084                 .ptr            = &Globals.szAnnounceVersion,
2085                 .special        = NULL,
2086                 .enum_list      = NULL,
2087                 .flags          = FLAG_ADVANCED,
2088         },
2089         {
2090                 .label          = "announce as",
2091                 .type           = P_ENUM,
2092                 .p_class        = P_GLOBAL,
2093                 .ptr            = &Globals.announce_as,
2094                 .special        = NULL,
2095                 .enum_list      = enum_announce_as,
2096                 .flags          = FLAG_ADVANCED,
2097         },
2098         {
2099                 .label          = "map acl inherit",
2100                 .type           = P_BOOL,
2101                 .p_class        = P_LOCAL,
2102                 .ptr            = &sDefault.bMap_acl_inherit,
2103                 .special        = NULL,
2104                 .enum_list      = NULL,
2105                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
2106         },
2107         {
2108                 .label          = "afs share",
2109                 .type           = P_BOOL,
2110                 .p_class        = P_LOCAL,
2111                 .ptr            = &sDefault.bAfs_Share,
2112                 .special        = NULL,
2113                 .enum_list      = NULL,
2114                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
2115         },
2116         {
2117                 .label          = "max mux",
2118                 .type           = P_INTEGER,
2119                 .p_class        = P_GLOBAL,
2120                 .ptr            = &Globals.max_mux,
2121                 .special        = NULL,
2122                 .enum_list      = NULL,
2123                 .flags          = FLAG_ADVANCED,
2124         },
2125         {
2126                 .label          = "max xmit",
2127                 .type           = P_INTEGER,
2128                 .p_class        = P_GLOBAL,
2129                 .ptr            = &Globals.max_xmit,
2130                 .special        = NULL,
2131                 .enum_list      = NULL,
2132                 .flags          = FLAG_ADVANCED,
2133         },
2134         {
2135                 .label          = "name resolve order",
2136                 .type           = P_STRING,
2137                 .p_class        = P_GLOBAL,
2138                 .ptr            = &Globals.szNameResolveOrder,
2139                 .special        = NULL,
2140                 .enum_list      = NULL,
2141                 .flags          = FLAG_ADVANCED | FLAG_WIZARD,
2142         },
2143         {
2144                 .label          = "max ttl",
2145                 .type           = P_INTEGER,
2146                 .p_class        = P_GLOBAL,
2147                 .ptr            = &Globals.max_ttl,
2148                 .special        = NULL,
2149                 .enum_list      = NULL,
2150                 .flags          = FLAG_ADVANCED,
2151         },
2152         {
2153                 .label          = "max wins ttl",
2154                 .type           = P_INTEGER,
2155                 .p_class        = P_GLOBAL,
2156                 .ptr            = &Globals.max_wins_ttl,
2157                 .special        = NULL,
2158                 .enum_list      = NULL,
2159                 .flags          = FLAG_ADVANCED,
2160         },
2161         {
2162                 .label          = "min wins ttl",
2163                 .type           = P_INTEGER,
2164                 .p_class        = P_GLOBAL,
2165                 .ptr            = &Globals.min_wins_ttl,
2166                 .special        = NULL,
2167                 .enum_list      = NULL,
2168                 .flags          = FLAG_ADVANCED,
2169         },
2170         {
2171                 .label          = "time server",
2172                 .type           = P_BOOL,
2173                 .p_class        = P_GLOBAL,
2174                 .ptr            = &Globals.bTimeServer,
2175                 .special        = NULL,
2176                 .enum_list      = NULL,
2177                 .flags          = FLAG_ADVANCED,
2178         },
2179         {
2180                 .label          = "unix extensions",
2181                 .type           = P_BOOL,
2182                 .p_class        = P_GLOBAL,
2183                 .ptr            = &Globals.bUnixExtensions,
2184                 .special        = NULL,
2185                 .enum_list      = NULL,
2186                 .flags          = FLAG_ADVANCED,
2187         },
2188         {
2189                 .label          = "use spnego",
2190                 .type           = P_BOOL,
2191                 .p_class        = P_GLOBAL,
2192                 .ptr            = &Globals.bUseSpnego,
2193                 .special        = NULL,
2194                 .enum_list      = NULL,
2195                 .flags          = FLAG_ADVANCED,
2196         },
2197         {
2198                 .label          = "client signing",
2199                 .type           = P_ENUM,
2200                 .p_class        = P_GLOBAL,
2201                 .ptr            = &Globals.client_signing,
2202                 .special        = NULL,
2203                 .enum_list      = enum_smb_signing_vals,
2204                 .flags          = FLAG_ADVANCED,
2205         },
2206         {
2207                 .label          = "server signing",
2208                 .type           = P_ENUM,
2209                 .p_class        = P_GLOBAL,
2210                 .ptr            = &Globals.server_signing,
2211                 .special        = NULL,
2212                 .enum_list      = enum_smb_signing_vals,
2213                 .flags          = FLAG_ADVANCED,
2214         },
2215         {
2216                 .label          = "smb encrypt",
2217                 .type           = P_ENUM,
2218                 .p_class        = P_LOCAL,
2219                 .ptr            = &sDefault.ismb_encrypt,
2220                 .special        = NULL,
2221                 .enum_list      = enum_smb_signing_vals,
2222                 .flags          = FLAG_ADVANCED,
2223         },
2224         {
2225                 .label          = "client use spnego",
2226                 .type           = P_BOOL,
2227                 .p_class        = P_GLOBAL,
2228                 .ptr            = &Globals.bClientUseSpnego,
2229                 .special        = NULL,
2230                 .enum_list      = NULL,
2231                 .flags          = FLAG_ADVANCED,
2232         },
2233         {
2234                 .label          = "client ldap sasl wrapping",
2235                 .type           = P_ENUM,
2236                 .p_class        = P_GLOBAL,
2237                 .ptr            = &Globals.client_ldap_sasl_wrapping,
2238                 .special        = NULL,
2239                 .enum_list      = enum_ldap_sasl_wrapping,
2240                 .flags          = FLAG_ADVANCED,
2241         },
2242         {
2243                 .label          = "enable asu support",
2244                 .type           = P_BOOL,
2245                 .p_class        = P_GLOBAL,
2246                 .ptr            = &Globals.bASUSupport,
2247                 .special        = NULL,
2248                 .enum_list      = NULL,
2249                 .flags          = FLAG_ADVANCED,
2250         },
2251         {
2252                 .label          = "svcctl list",
2253                 .type           = P_LIST,
2254                 .p_class        = P_GLOBAL,
2255                 .ptr            = &Globals.szServicesList,
2256                 .special        = NULL,
2257                 .enum_list      = NULL,
2258                 .flags          = FLAG_ADVANCED,
2259         },
2260
2261         {N_("Tuning Options"), P_SEP, P_SEPARATOR},
2262
2263         {
2264                 .label          = "block size",
2265                 .type           = P_INTEGER,
2266                 .p_class        = P_LOCAL,
2267                 .ptr            = &sDefault.iBlock_size,
2268                 .special        = NULL,
2269                 .enum_list      = NULL,
2270                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
2271         },
2272         {
2273                 .label          = "deadtime",
2274                 .type           = P_INTEGER,
2275                 .p_class        = P_GLOBAL,
2276                 .ptr            = &Globals.deadtime,
2277                 .special        = NULL,
2278                 .enum_list      = NULL,
2279                 .flags          = FLAG_ADVANCED,
2280         },
2281         {
2282                 .label          = "getwd cache",
2283                 .type           = P_BOOL,
2284                 .p_class        = P_GLOBAL,
2285                 .ptr            = &Globals.getwd_cache,
2286                 .special        = NULL,
2287                 .enum_list      = NULL,
2288                 .flags          = FLAG_ADVANCED,
2289         },
2290         {
2291                 .label          = "keepalive",
2292                 .type           = P_INTEGER,
2293                 .p_class        = P_GLOBAL,
2294                 .ptr            = &Globals.iKeepalive,
2295                 .special        = NULL,
2296                 .enum_list      = NULL,
2297                 .flags          = FLAG_ADVANCED,
2298         },
2299         {
2300                 .label          = "change notify",
2301                 .type           = P_BOOL,
2302                 .p_class        = P_LOCAL,
2303                 .ptr            = &sDefault.bChangeNotify,
2304                 .special        = NULL,
2305                 .enum_list      = NULL,
2306                 .flags          = FLAG_ADVANCED | FLAG_SHARE,
2307         },
2308         {
2309                 .label          = "directory name cache size",
2310                 .type           = P_INTEGER,
2311                 .p_class        = P_LOCAL,
2312                 .ptr            = &sDefault.iDirectoryNameCacheSize,
2313                 .special        = NULL,
2314                 .enum_list      = NULL,
2315                 .flags          = FLAG_ADVANCED | FLAG_SHARE,
2316         },
2317         {
2318                 .label          = "kernel change notify",
2319                 .type           = P_BOOL,
2320                 .p_class        = P_LOCAL,
2321                 .ptr            = &sDefault.bKernelChangeNotify,
2322                 .special        = NULL,
2323                 .enum_list      = NULL,
2324                 .flags          = FLAG_ADVANCED | FLAG_SHARE,
2325         },
2326         {
2327                 .label          = "lpq cache time",
2328                 .type           = P_INTEGER,
2329                 .p_class        = P_GLOBAL,
2330                 .ptr            = &Globals.lpqcachetime,
2331                 .special        = NULL,
2332                 .enum_list      = NULL,
2333                 .flags          = FLAG_ADVANCED,
2334         },
2335         {
2336                 .label          = "max smbd processes",
2337                 .type           = P_INTEGER,
2338                 .p_class        = P_GLOBAL,
2339                 .ptr            = &Globals.iMaxSmbdProcesses,
2340                 .special        = NULL,
2341                 .enum_list      = NULL,
2342                 .flags          = FLAG_ADVANCED,
2343         },
2344         {
2345                 .label          = "max connections",
2346                 .type           = P_INTEGER,
2347                 .p_class        = P_LOCAL,
2348                 .ptr            = &sDefault.iMaxConnections,
2349                 .special        = NULL,
2350                 .enum_list      = NULL,
2351                 .flags          = FLAG_ADVANCED | FLAG_SHARE,
2352         },
2353         {
2354                 .label          = "paranoid server security",
2355                 .type           = P_BOOL,
2356                 .p_class        = P_GLOBAL,
2357                 .ptr            = &Globals.paranoid_server_security,
2358                 .special        = NULL,
2359                 .enum_list      = NULL,
2360                 .flags          = FLAG_ADVANCED,
2361         },
2362         {
2363                 .label          = "max disk size",
2364                 .type           = P_INTEGER,
2365                 .p_class        = P_GLOBAL,
2366                 .ptr            = &Globals.maxdisksize,
2367                 .special        = NULL,
2368                 .enum_list      = NULL,
2369                 .flags          = FLAG_ADVANCED,
2370         },
2371         {
2372                 .label          = "max open files",
2373                 .type           = P_INTEGER,
2374                 .p_class        = P_GLOBAL,
2375                 .ptr            = &Globals.max_open_files,
2376                 .special        = NULL,
2377                 .enum_list      = NULL,
2378                 .flags          = FLAG_ADVANCED,
2379         },
2380         {
2381                 .label          = "min print space",
2382                 .type           = P_INTEGER,
2383                 .p_class        = P_LOCAL,
2384                 .ptr            = &sDefault.iMinPrintSpace,
2385                 .special        = NULL,
2386                 .enum_list      = NULL,
2387                 .flags          = FLAG_ADVANCED | FLAG_PRINT,
2388         },
2389         {
2390                 .label          = "socket options",
2391                 .type           = P_STRING,
2392                 .p_class        = P_GLOBAL,
2393                 .ptr            = &Globals.szSocketOptions,
2394                 .special        = NULL,
2395                 .enum_list      = NULL,
2396                 .flags          = FLAG_ADVANCED,
2397         },
2398         {
2399                 .label          = "strict allocate",
2400                 .type           = P_BOOL,
2401                 .p_class        = P_LOCAL,
2402                 .ptr            = &sDefault.bStrictAllocate,
2403                 .special        = NULL,
2404                 .enum_list      = NULL,
2405                 .flags          = FLAG_ADVANCED | FLAG_SHARE,
2406         },
2407         {
2408                 .label          = "strict sync",
2409                 .type           = P_BOOL,
2410                 .p_class        = P_LOCAL,
2411                 .ptr            = &sDefault.bStrictSync,
2412                 .special        = NULL,
2413                 .enum_list      = NULL,
2414                 .flags          = FLAG_ADVANCED | FLAG_SHARE,
2415         },
2416         {
2417                 .label          = "sync always",
2418                 .type           = P_BOOL,
2419                 .p_class        = P_LOCAL,
2420                 .ptr            = &sDefault.bSyncAlways,
2421                 .special        = NULL,
2422                 .enum_list      = NULL,
2423                 .flags          = FLAG_ADVANCED | FLAG_SHARE,
2424         },
2425         {
2426                 .label          = "use mmap",
2427                 .type           = P_BOOL,
2428                 .p_class        = P_GLOBAL,
2429                 .ptr            = &Globals.bUseMmap,
2430                 .special        = NULL,
2431                 .enum_list      = NULL,
2432                 .flags          = FLAG_ADVANCED,
2433         },
2434         {
2435                 .label          = "use sendfile",
2436                 .type           = P_BOOL,
2437                 .p_class        = P_LOCAL,
2438                 .ptr            = &sDefault.bUseSendfile,
2439                 .special        = NULL,
2440                 .enum_list      = NULL,
2441                 .flags          = FLAG_ADVANCED | FLAG_SHARE,
2442         },
2443         {
2444                 .label          = "hostname lookups",
2445                 .type           = P_BOOL,
2446                 .p_class        = P_GLOBAL,
2447                 .ptr            = &Globals.bHostnameLookups,
2448                 .special        = NULL,
2449                 .enum_list      = NULL,
2450                 .flags          = FLAG_ADVANCED,
2451         },
2452         {
2453                 .label          = "write cache size",
2454                 .type           = P_INTEGER,
2455                 .p_class        = P_LOCAL,
2456                 .ptr            = &sDefault.iWriteCacheSize,
2457                 .special        = NULL,
2458                 .enum_list      = NULL,
2459                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_DEPRECATED,
2460         },
2461         {
2462                 .label          = "name cache timeout",
2463                 .type           = P_INTEGER,
2464                 .p_class        = P_GLOBAL,
2465                 .ptr            = &Globals.name_cache_timeout,
2466                 .special        = NULL,
2467                 .enum_list      = NULL,
2468                 .flags          = FLAG_ADVANCED,
2469         },
2470         {
2471                 .label          = "ctdbd socket",
2472                 .type           = P_STRING,
2473                 .p_class        = P_GLOBAL,
2474                 .ptr            = &Globals.ctdbdSocket,
2475                 .special        = NULL,
2476                 .enum_list      = NULL,
2477                 .flags          = FLAG_ADVANCED | FLAG_GLOBAL,
2478         },
2479         {
2480                 .label          = "cluster addresses",
2481                 .type           = P_LIST,
2482                 .p_class        = P_GLOBAL,
2483                 .ptr            = &Globals.szClusterAddresses,
2484                 .special        = NULL,
2485                 .enum_list      = NULL,
2486                 .flags          = FLAG_ADVANCED | FLAG_GLOBAL,
2487         },
2488         {
2489                 .label          = "clustering",
2490                 .type           = P_BOOL,
2491                 .p_class        = P_GLOBAL,
2492                 .ptr            = &Globals.clustering,
2493                 .special        = NULL,
2494                 .enum_list      = NULL,
2495                 .flags          = FLAG_ADVANCED | FLAG_GLOBAL,
2496         },
2497
2498         {N_("Printing Options"), P_SEP, P_SEPARATOR},
2499
2500         {
2501                 .label          = "max reported print jobs",
2502                 .type           = P_INTEGER,
2503                 .p_class        = P_LOCAL,
2504                 .ptr            = &sDefault.iMaxReportedPrintJobs,
2505                 .special        = NULL,
2506                 .enum_list      = NULL,
2507                 .flags          = FLAG_ADVANCED | FLAG_PRINT,
2508         },
2509         {
2510                 .label          = "max print jobs",
2511                 .type           = P_INTEGER,
2512                 .p_class        = P_LOCAL,
2513                 .ptr            = &sDefault.iMaxPrintJobs,
2514                 .special        = NULL,
2515                 .enum_list      = NULL,
2516                 .flags          = FLAG_ADVANCED | FLAG_PRINT,
2517         },
2518         {
2519                 .label          = "load printers",
2520                 .type           = P_BOOL,
2521                 .p_class        = P_GLOBAL,
2522                 .ptr            = &Globals.bLoadPrinters,
2523                 .special        = NULL,
2524                 .enum_list      = NULL,
2525                 .flags          = FLAG_ADVANCED | FLAG_PRINT,
2526         },
2527         {
2528                 .label          = "printcap cache time",
2529                 .type           = P_INTEGER,
2530                 .p_class        = P_GLOBAL,
2531                 .ptr            = &Globals.PrintcapCacheTime,
2532                 .special        = NULL,
2533                 .enum_list      = NULL,
2534                 .flags          = FLAG_ADVANCED | FLAG_PRINT,
2535         },
2536         {
2537                 .label          = "printcap name",
2538                 .type           = P_STRING,
2539                 .p_class        = P_GLOBAL,
2540                 .ptr            = &Globals.szPrintcapname,
2541                 .special        = NULL,
2542                 .enum_list      = NULL,
2543                 .flags          = FLAG_ADVANCED | FLAG_PRINT,
2544         },
2545         {
2546                 .label          = "printcap",
2547                 .type           = P_STRING,
2548                 .p_class        = P_GLOBAL,
2549                 .ptr            = &Globals.szPrintcapname,
2550                 .special        = NULL,
2551                 .enum_list      = NULL,
2552                 .flags          = FLAG_HIDE,
2553         },
2554         {
2555                 .label          = "printable",
2556                 .type           = P_BOOL,
2557                 .p_class        = P_LOCAL,
2558                 .ptr            = &sDefault.bPrint_ok,
2559                 .special        = NULL,
2560                 .enum_list      = NULL,
2561                 .flags          = FLAG_ADVANCED | FLAG_PRINT,
2562         },
2563         {
2564                 .label          = "print ok",
2565                 .type           = P_BOOL,
2566                 .p_class        = P_LOCAL,
2567                 .ptr            = &sDefault.bPrint_ok,
2568                 .special        = NULL,
2569                 .enum_list      = NULL,
2570                 .flags          = FLAG_HIDE,
2571         },
2572         {
2573                 .label          = "printing",
2574                 .type           = P_ENUM,
2575                 .p_class        = P_LOCAL,
2576                 .ptr            = &sDefault.iPrinting,
2577                 .special        = handle_printing,
2578                 .enum_list      = enum_printing,
2579                 .flags          = FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL,
2580         },
2581         {
2582                 .label          = "cups options",
2583                 .type           = P_STRING,
2584                 .p_class        = P_LOCAL,
2585                 .ptr            = &sDefault.szCupsOptions,
2586                 .special        = NULL,
2587                 .enum_list      = NULL,
2588                 .flags          = FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL,
2589         },
2590         {
2591                 .label          = "cups server",
2592                 .type           = P_STRING,
2593                 .p_class        = P_GLOBAL,
2594                 .ptr            = &Globals.szCupsServer,
2595                 .special        = NULL,
2596                 .enum_list      = NULL,
2597                 .flags          = FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL,
2598         },
2599         {
2600                 .label          = "cups connection timeout",
2601                 .type           = P_INTEGER,
2602                 .p_class        = P_GLOBAL,
2603                 .ptr            = &Globals.cups_connection_timeout,
2604                 .special        = NULL,
2605                 .enum_list      = NULL,
2606                 .flags          = FLAG_ADVANCED,
2607         },
2608         {
2609                 .label          = "iprint server",
2610                 .type           = P_STRING,
2611                 .p_class        = P_GLOBAL,
2612                 .ptr            = &Globals.szIPrintServer,
2613                 .special        = NULL,
2614                 .enum_list      = NULL,
2615                 .flags          = FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL,
2616         },
2617         {
2618                 .label          = "print command",
2619                 .type           = P_STRING,
2620                 .p_class        = P_LOCAL,
2621                 .ptr            = &sDefault.szPrintcommand,
2622                 .special        = NULL,
2623                 .enum_list      = NULL,
2624                 .flags          = FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL,
2625         },
2626         {
2627                 .label          = "disable spoolss",
2628                 .type           = P_BOOL,
2629                 .p_class        = P_GLOBAL,
2630                 .ptr            = &Globals.bDisableSpoolss,
2631                 .special        = NULL,
2632                 .enum_list      = NULL,
2633                 .flags          = FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL,
2634         },
2635         {
2636                 .label          = "enable spoolss",
2637                 .type           = P_BOOLREV,
2638                 .p_class        = P_GLOBAL,
2639                 .ptr            = &Globals.bDisableSpoolss,
2640                 .special        = NULL,
2641                 .enum_list      = NULL,
2642                 .flags          = FLAG_HIDE,
2643         },
2644         {
2645                 .label          = "lpq command",
2646                 .type           = P_STRING,
2647                 .p_class        = P_LOCAL,
2648                 .ptr            = &sDefault.szLpqcommand,
2649                 .special        = NULL,
2650                 .enum_list      = NULL,
2651                 .flags          = FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL,
2652         },
2653         {
2654                 .label          = "lprm command",
2655                 .type           = P_STRING,
2656                 .p_class        = P_LOCAL,
2657                 .ptr            = &sDefault.szLprmcommand,
2658                 .special        = NULL,
2659                 .enum_list      = NULL,
2660                 .flags          = FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL,
2661         },
2662         {
2663                 .label          = "lppause command",
2664                 .type           = P_STRING,
2665                 .p_class        = P_LOCAL,
2666                 .ptr            = &sDefault.szLppausecommand,
2667                 .special        = NULL,
2668                 .enum_list      = NULL,
2669                 .flags          = FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL,
2670         },
2671         {
2672                 .label          = "lpresume command",
2673                 .type           = P_STRING,
2674                 .p_class        = P_LOCAL,
2675                 .ptr            = &sDefault.szLpresumecommand,
2676                 .special        = NULL,
2677                 .enum_list      = NULL,
2678                 .flags          = FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL,
2679         },
2680         {
2681                 .label          = "queuepause command",
2682                 .type           = P_STRING,
2683                 .p_class        = P_LOCAL,
2684                 .ptr            = &sDefault.szQueuepausecommand,
2685                 .special        = NULL,
2686                 .enum_list      = NULL,
2687                 .flags          = FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL,
2688         },
2689         {
2690                 .label          = "queueresume command",
2691                 .type           = P_STRING,
2692                 .p_class        = P_LOCAL,
2693                 .ptr            = &sDefault.szQueueresumecommand,
2694                 .special        = NULL,
2695                 .enum_list      = NULL,
2696                 .flags          = FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL,
2697         },
2698         {
2699                 .label          = "addport command",
2700                 .type           = P_STRING,
2701                 .p_class        = P_GLOBAL,
2702                 .ptr            = &Globals.szAddPortCommand,
2703                 .special        = NULL,
2704                 .enum_list      = NULL,
2705                 .flags          = FLAG_ADVANCED,
2706         },
2707         {
2708                 .label          = "enumports command",
2709                 .type           = P_STRING,
2710                 .p_class        = P_GLOBAL,
2711                 .ptr            = &Globals.szEnumPortsCommand,
2712                 .special        = NULL,
2713                 .enum_list      = NULL,
2714                 .flags          = FLAG_ADVANCED,
2715         },
2716         {
2717                 .label          = "addprinter command",
2718                 .type           = P_STRING,
2719                 .p_class        = P_GLOBAL,
2720                 .ptr            = &Globals.szAddPrinterCommand,
2721                 .special        = NULL,
2722                 .enum_list      = NULL,
2723                 .flags          = FLAG_ADVANCED,
2724         },
2725         {
2726                 .label          = "deleteprinter command",
2727                 .type           = P_STRING,
2728                 .p_class        = P_GLOBAL,
2729                 .ptr            = &Globals.szDeletePrinterCommand,
2730                 .special        = NULL,
2731                 .enum_list      = NULL,
2732                 .flags          = FLAG_ADVANCED,
2733         },
2734         {
2735                 .label          = "show add printer wizard",
2736                 .type           = P_BOOL,
2737                 .p_class        = P_GLOBAL,
2738                 .ptr            = &Globals.bMsAddPrinterWizard,
2739                 .special        = NULL,
2740                 .enum_list      = NULL,
2741                 .flags          = FLAG_ADVANCED,
2742         },
2743         {
2744                 .label          = "os2 driver map",
2745                 .type           = P_STRING,
2746                 .p_class        = P_GLOBAL,
2747                 .ptr            = &Globals.szOs2DriverMap,
2748                 .special        = NULL,
2749                 .enum_list      = NULL,
2750                 .flags          = FLAG_ADVANCED,
2751         },
2752
2753         {
2754                 .label          = "printer name",
2755                 .type           = P_STRING,
2756                 .p_class        = P_LOCAL,
2757                 .ptr            = &sDefault.szPrintername,
2758                 .special        = NULL,
2759                 .enum_list      = NULL,
2760                 .flags          = FLAG_ADVANCED | FLAG_PRINT,
2761         },
2762         {
2763                 .label          = "printer",
2764                 .type           = P_STRING,
2765                 .p_class        = P_LOCAL,
2766                 .ptr            = &sDefault.szPrintername,
2767                 .special        = NULL,
2768                 .enum_list      = NULL,
2769                 .flags          = FLAG_HIDE,
2770         },
2771         {
2772                 .label          = "use client driver",
2773                 .type           = P_BOOL,
2774                 .p_class        = P_LOCAL,
2775                 .ptr            = &sDefault.bUseClientDriver,
2776                 .special        = NULL,
2777                 .enum_list      = NULL,
2778                 .flags          = FLAG_ADVANCED | FLAG_PRINT,
2779         },
2780         {
2781                 .label          = "default devmode",
2782                 .type           = P_BOOL,
2783                 .p_class        = P_LOCAL,
2784                 .ptr            = &sDefault.bDefaultDevmode,
2785                 .special        = NULL,
2786                 .enum_list      = NULL,
2787                 .flags          = FLAG_ADVANCED | FLAG_PRINT,
2788         },
2789         {
2790                 .label          = "force printername",
2791                 .type           = P_BOOL,
2792                 .p_class        = P_LOCAL,
2793                 .ptr            = &sDefault.bForcePrintername,
2794                 .special        = NULL,
2795                 .enum_list      = NULL,
2796                 .flags          = FLAG_ADVANCED | FLAG_PRINT,
2797         },
2798         {
2799                 .label          = "printjob username",
2800                 .type           = P_STRING,
2801                 .p_class        = P_LOCAL,
2802                 .ptr            = &sDefault.szPrintjobUsername,
2803                 .special        = NULL,
2804                 .enum_list      = NULL,
2805                 .flags          = FLAG_ADVANCED | FLAG_PRINT,
2806         },
2807
2808         {N_("Filename Handling"), P_SEP, P_SEPARATOR},
2809
2810         {
2811                 .label          = "mangling method",
2812                 .type           = P_STRING,
2813                 .p_class        = P_GLOBAL,
2814                 .ptr            = &Globals.szManglingMethod,
2815                 .special        = NULL,
2816                 .enum_list      = NULL,
2817                 .flags          = FLAG_ADVANCED,
2818         },
2819         {
2820                 .label          = "mangle prefix",
2821                 .type           = P_INTEGER,
2822                 .p_class        = P_GLOBAL,
2823                 .ptr            = &Globals.mangle_prefix,
2824                 .special        = NULL,
2825                 .enum_list      = NULL,
2826                 .flags          = FLAG_ADVANCED,
2827         },
2828
2829         {
2830                 .label          = "default case",
2831                 .type           = P_ENUM,
2832                 .p_class        = P_LOCAL,
2833                 .ptr            = &sDefault.iDefaultCase,
2834                 .special        = NULL,
2835                 .enum_list      = enum_case,
2836                 .flags          = FLAG_ADVANCED | FLAG_SHARE,
2837         },
2838         {
2839                 .label          = "case sensitive",
2840                 .type           = P_ENUM,
2841                 .p_class        = P_LOCAL,
2842                 .ptr            = &sDefault.iCaseSensitive,
2843                 .special        = NULL,
2844                 .enum_list      = enum_bool_auto,
2845                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
2846         },
2847         {
2848                 .label          = "casesignames",
2849                 .type           = P_ENUM,
2850                 .p_class        = P_LOCAL,
2851                 .ptr            = &sDefault.iCaseSensitive,
2852                 .special        = NULL,
2853                 .enum_list      = enum_bool_auto,
2854                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL | FLAG_HIDE,
2855         },
2856         {
2857                 .label          = "preserve case",
2858                 .type           = P_BOOL,
2859                 .p_class        = P_LOCAL,
2860                 .ptr            = &sDefault.bCasePreserve,
2861                 .special        = NULL,
2862                 .enum_list      = NULL,
2863                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
2864         },
2865         {
2866                 .label          = "short preserve case",
2867                 .type           = P_BOOL,
2868                 .p_class        = P_LOCAL,
2869                 .ptr            = &sDefault.bShortCasePreserve,
2870                 .special        = NULL,
2871                 .enum_list      = NULL,
2872                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
2873         },
2874         {
2875                 .label          = "mangling char",
2876                 .type           = P_CHAR,
2877                 .p_class        = P_LOCAL,
2878                 .ptr            = &sDefault.magic_char,
2879                 .special        = NULL,
2880                 .enum_list      = NULL,
2881                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
2882         },
2883         {
2884                 .label          = "hide dot files",
2885                 .type           = P_BOOL,
2886                 .p_class        = P_LOCAL,
2887                 .ptr            = &sDefault.bHideDotFiles,
2888                 .special        = NULL,
2889                 .enum_list      = NULL,
2890                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
2891         },
2892         {
2893                 .label          = "hide special files",
2894                 .type           = P_BOOL,
2895                 .p_class        = P_LOCAL,
2896                 .ptr            = &sDefault.bHideSpecialFiles,
2897                 .special        = NULL,
2898                 .enum_list      = NULL,
2899                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
2900         },
2901         {
2902                 .label          = "hide unreadable",
2903                 .type           = P_BOOL,
2904                 .p_class        = P_LOCAL,
2905                 .ptr            = &sDefault.bHideUnReadable,
2906                 .special        = NULL,
2907                 .enum_list      = NULL,
2908                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
2909         },
2910         {
2911                 .label          = "hide unwriteable files",
2912                 .type           = P_BOOL,
2913                 .p_class        = P_LOCAL,
2914                 .ptr            = &sDefault.bHideUnWriteableFiles,
2915                 .special        = NULL,
2916                 .enum_list      = NULL,
2917                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
2918         },
2919         {
2920                 .label          = "delete veto files",
2921                 .type           = P_BOOL,
2922                 .p_class        = P_LOCAL,
2923                 .ptr            = &sDefault.bDeleteVetoFiles,
2924                 .special        = NULL,
2925                 .enum_list      = NULL,
2926                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
2927         },
2928         {
2929                 .label          = "veto files",
2930                 .type           = P_STRING,
2931                 .p_class        = P_LOCAL,
2932                 .ptr            = &sDefault.szVetoFiles,
2933                 .special        = NULL,
2934                 .enum_list      = NULL,
2935                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
2936         },
2937         {
2938                 .label          = "hide files",
2939                 .type           = P_STRING,
2940                 .p_class        = P_LOCAL,
2941                 .ptr            = &sDefault.szHideFiles,
2942                 .special        = NULL,
2943                 .enum_list      = NULL,
2944                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
2945         },
2946         {
2947                 .label          = "veto oplock files",
2948                 .type           = P_STRING,
2949                 .p_class        = P_LOCAL,
2950                 .ptr            = &sDefault.szVetoOplockFiles,
2951                 .special        = NULL,
2952                 .enum_list      = NULL,
2953                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
2954         },
2955         {
2956                 .label          = "map archive",
2957                 .type           = P_BOOL,
2958                 .p_class        = P_LOCAL,
2959                 .ptr            = &sDefault.bMap_archive,
2960                 .special        = NULL,
2961                 .enum_list      = NULL,
2962                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
2963         },
2964         {
2965                 .label          = "map hidden",
2966                 .type           = P_BOOL,
2967                 .p_class        = P_LOCAL,
2968                 .ptr            = &sDefault.bMap_hidden,
2969                 .special        = NULL,
2970                 .enum_list      = NULL,
2971                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
2972         },
2973         {
2974                 .label          = "map system",
2975                 .type           = P_BOOL,
2976                 .p_class        = P_LOCAL,
2977                 .ptr            = &sDefault.bMap_system,
2978                 .special        = NULL,
2979                 .enum_list      = NULL,
2980                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
2981         },
2982         {
2983                 .label          = "map readonly",
2984                 .type           = P_ENUM,
2985                 .p_class        = P_LOCAL,
2986                 .ptr            = &sDefault.iMap_readonly,
2987                 .special        = NULL,
2988                 .enum_list      = enum_map_readonly,
2989                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
2990         },
2991         {
2992                 .label          = "mangled names",
2993                 .type           = P_BOOL,
2994                 .p_class        = P_LOCAL,
2995                 .ptr            = &sDefault.bMangledNames,
2996                 .special        = NULL,
2997                 .enum_list      = NULL,
2998                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
2999         },
3000         {
3001                 .label          = "max stat cache size",
3002                 .type           = P_INTEGER,
3003                 .p_class        = P_GLOBAL,
3004                 .ptr            = &Globals.iMaxStatCacheSize,
3005                 .special        = NULL,
3006                 .enum_list      = NULL,
3007                 .flags          = FLAG_ADVANCED,
3008         },
3009         {
3010                 .label          = "stat cache",
3011                 .type           = P_BOOL,
3012                 .p_class        = P_GLOBAL,
3013                 .ptr            = &Globals.bStatCache,
3014                 .special        = NULL,
3015                 .enum_list      = NULL,
3016                 .flags          = FLAG_ADVANCED,
3017         },
3018         {
3019                 .label          = "store dos attributes",
3020                 .type           = P_BOOL,
3021                 .p_class        = P_LOCAL,
3022                 .ptr            = &sDefault.bStoreDosAttributes,
3023                 .special        = NULL,
3024                 .enum_list      = NULL,
3025                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
3026         },
3027         {
3028                 .label          = "dmapi support",
3029                 .type           = P_BOOL,
3030                 .p_class        = P_LOCAL,
3031                 .ptr            = &sDefault.bDmapiSupport,
3032                 .special        = NULL,
3033                 .enum_list      = NULL,
3034                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
3035         },
3036
3037
3038         {N_("Domain Options"), P_SEP, P_SEPARATOR},
3039
3040         {
3041                 .label          = "machine password timeout",
3042                 .type           = P_INTEGER,
3043                 .p_class        = P_GLOBAL,
3044                 .ptr            = &Globals.machine_password_timeout,
3045                 .special        = NULL,
3046                 .enum_list      = NULL,
3047                 .flags          = FLAG_ADVANCED | FLAG_WIZARD,
3048         },
3049
3050         {N_("Logon Options"), P_SEP, P_SEPARATOR},
3051
3052         {
3053                 .label          = "add user script",
3054                 .type           = P_STRING,
3055                 .p_class        = P_GLOBAL,
3056                 .ptr            = &Globals.szAddUserScript,
3057                 .special        = NULL,
3058                 .enum_list      = NULL,
3059                 .flags          = FLAG_ADVANCED,
3060         },
3061         {
3062                 .label          = "rename user script",
3063                 .type           = P_STRING,
3064                 .p_class        = P_GLOBAL,
3065                 .ptr            = &Globals.szRenameUserScript,
3066                 .special        = NULL,
3067                 .enum_list      = NULL,
3068                 .flags          = FLAG_ADVANCED,
3069         },
3070         {
3071                 .label          = "delete user script",
3072                 .type           = P_STRING,
3073                 .p_class        = P_GLOBAL,
3074                 .ptr            = &Globals.szDelUserScript,
3075                 .special        = NULL,
3076                 .enum_list      = NULL,
3077                 .flags          = FLAG_ADVANCED,
3078         },
3079         {
3080                 .label          = "add group script",
3081                 .type           = P_STRING,
3082                 .p_class        = P_GLOBAL,
3083                 .ptr            = &Globals.szAddGroupScript,
3084                 .special        = NULL,
3085                 .enum_list      = NULL,
3086                 .flags          = FLAG_ADVANCED,
3087         },
3088         {
3089                 .label          = "delete group script",
3090                 .type           = P_STRING,
3091                 .p_class        = P_GLOBAL,
3092                 .ptr            = &Globals.szDelGroupScript,
3093                 .special        = NULL,
3094                 .enum_list      = NULL,
3095                 .flags          = FLAG_ADVANCED,
3096         },
3097         {
3098                 .label          = "add user to group script",
3099                 .type           = P_STRING,
3100                 .p_class        = P_GLOBAL,
3101                 .ptr            = &Globals.szAddUserToGroupScript,
3102                 .special        = NULL,
3103                 .enum_list      = NULL,
3104                 .flags          = FLAG_ADVANCED,
3105         },
3106         {
3107                 .label          = "delete user from group script",
3108                 .type           = P_STRING,
3109                 .p_class        = P_GLOBAL,
3110                 .ptr            = &Globals.szDelUserFromGroupScript,
3111                 .special        = NULL,
3112                 .enum_list      = NULL,
3113                 .flags          = FLAG_ADVANCED,
3114         },
3115         {
3116                 .label          = "set primary group script",
3117                 .type           = P_STRING,
3118                 .p_class        = P_GLOBAL,
3119                 .ptr            = &Globals.szSetPrimaryGroupScript,
3120                 .special        = NULL,
3121                 .enum_list      = NULL,
3122                 .flags          = FLAG_ADVANCED,
3123         },
3124         {
3125                 .label          = "add machine script",
3126                 .type           = P_STRING,
3127                 .p_class        = P_GLOBAL,
3128                 .ptr            = &Globals.szAddMachineScript,
3129                 .special        = NULL,
3130                 .enum_list      = NULL,
3131                 .flags          = FLAG_ADVANCED,
3132         },
3133         {
3134                 .label          = "shutdown script",
3135                 .type           = P_STRING,
3136                 .p_class        = P_GLOBAL,
3137                 .ptr            = &Globals.szShutdownScript,
3138                 .special        = NULL,
3139                 .enum_list      = NULL,
3140                 .flags          = FLAG_ADVANCED,
3141         },
3142         {
3143                 .label          = "abort shutdown script",
3144                 .type           = P_STRING,
3145                 .p_class        = P_GLOBAL,
3146                 .ptr            = &Globals.szAbortShutdownScript,
3147                 .special        = NULL,
3148                 .enum_list      = NULL,
3149                 .flags          = FLAG_ADVANCED,
3150         },
3151         {
3152                 .label          = "username map script",
3153                 .type           = P_STRING,
3154                 .p_class        = P_GLOBAL,
3155                 .ptr            = &Globals.szUsernameMapScript,
3156                 .special        = NULL,
3157                 .enum_list      = NULL,
3158                 .flags          = FLAG_ADVANCED,
3159         },
3160         {
3161                 .label          = "logon script",
3162                 .type           = P_STRING,
3163                 .p_class        = P_GLOBAL,
3164                 .ptr            = &Globals.szLogonScript,
3165                 .special        = NULL,
3166                 .enum_list      = NULL,
3167                 .flags          = FLAG_ADVANCED,
3168         },
3169         {
3170                 .label          = "logon path",
3171                 .type           = P_STRING,
3172                 .p_class        = P_GLOBAL,
3173                 .ptr            = &Globals.szLogonPath,
3174                 .special        = NULL,
3175                 .enum_list      = NULL,
3176                 .flags          = FLAG_ADVANCED,
3177         },
3178         {
3179                 .label          = "logon drive",
3180                 .type           = P_STRING,
3181                 .p_class        = P_GLOBAL,
3182                 .ptr            = &Globals.szLogonDrive,
3183                 .special        = NULL,
3184                 .enum_list      = NULL,
3185                 .flags          = FLAG_ADVANCED,
3186         },
3187         {
3188                 .label          = "logon home",
3189                 .type           = P_STRING,
3190                 .p_class        = P_GLOBAL,
3191                 .ptr            = &Globals.szLogonHome,
3192                 .special        = NULL,
3193                 .enum_list      = NULL,
3194                 .flags          = FLAG_ADVANCED,
3195         },
3196         {
3197                 .label          = "domain logons",
3198                 .type           = P_BOOL,
3199                 .p_class        = P_GLOBAL,
3200                 .ptr            = &Globals.bDomainLogons,
3201                 .special        = NULL,
3202                 .enum_list      = NULL,
3203                 .flags          = FLAG_ADVANCED,
3204         },
3205
3206         {
3207                 .label          = "init logon delayed hosts",
3208                 .type           = P_LIST,
3209                 .p_class        = P_GLOBAL,
3210                 .ptr            = &Globals.szInitLogonDelayedHosts,
3211                 .flags          = FLAG_ADVANCED,
3212         },
3213
3214         {
3215                 .label          = "init logon delay",
3216                 .type           = P_INTEGER,
3217                 .p_class        = P_GLOBAL,
3218                 .ptr            = &Globals.InitLogonDelay,
3219                 .flags          = FLAG_ADVANCED,
3220
3221         },
3222
3223         {N_("Browse Options"), P_SEP, P_SEPARATOR},
3224
3225         {
3226                 .label          = "os level",
3227                 .type           = P_INTEGER,
3228                 .p_class        = P_GLOBAL,
3229                 .ptr            = &Globals.os_level,
3230                 .special        = NULL,
3231                 .enum_list      = NULL,
3232                 .flags          = FLAG_BASIC | FLAG_ADVANCED,
3233         },
3234         {
3235                 .label          = "lm announce",
3236                 .type           = P_ENUM,
3237                 .p_class        = P_GLOBAL,
3238                 .ptr            = &Globals.lm_announce,
3239                 .special        = NULL,
3240                 .enum_list      = enum_bool_auto,
3241                 .flags          = FLAG_ADVANCED,
3242         },
3243         {
3244                 .label          = "lm interval",
3245                 .type           = P_INTEGER,
3246                 .p_class        = P_GLOBAL,
3247                 .ptr            = &Globals.lm_interval,
3248                 .special        = NULL,
3249                 .enum_list      = NULL,
3250                 .flags          = FLAG_ADVANCED,
3251         },
3252         {
3253                 .label          = "preferred master",
3254                 .type           = P_ENUM,
3255                 .p_class        = P_GLOBAL,
3256                 .ptr            = &Globals.iPreferredMaster,
3257                 .special        = NULL,
3258                 .enum_list      = enum_bool_auto,
3259                 .flags          = FLAG_BASIC | FLAG_ADVANCED,
3260         },
3261         {
3262                 .label          = "prefered master",
3263                 .type           = P_ENUM,
3264                 .p_class        = P_GLOBAL,
3265                 .ptr            = &Globals.iPreferredMaster,
3266                 .special        = NULL,
3267                 .enum_list      = enum_bool_auto,
3268                 .flags          = FLAG_HIDE,
3269         },
3270         {
3271                 .label          = "local master",
3272                 .type           = P_BOOL,
3273                 .p_class        = P_GLOBAL,
3274                 .ptr            = &Globals.bLocalMaster,
3275                 .special        = NULL,
3276                 .enum_list      = NULL,
3277                 .flags          = FLAG_BASIC | FLAG_ADVANCED,
3278         },
3279         {
3280                 .label          = "domain master",
3281                 .type           = P_ENUM,
3282                 .p_class        = P_GLOBAL,
3283                 .ptr            = &Globals.iDomainMaster,
3284                 .special        = NULL,
3285                 .enum_list      = enum_bool_auto,
3286                 .flags          = FLAG_BASIC | FLAG_ADVANCED,
3287         },
3288         {
3289                 .label          = "browse list",
3290                 .type           = P_BOOL,
3291                 .p_class        = P_GLOBAL,
3292                 .ptr            = &Globals.bBrowseList,
3293                 .special        = NULL,
3294                 .enum_list      = NULL,
3295                 .flags          = FLAG_ADVANCED,
3296         },
3297         {
3298                 .label          = "browseable",
3299                 .type           = P_BOOL,
3300                 .p_class        = P_LOCAL,
3301                 .ptr            = &sDefault.bBrowseable,
3302                 .special        = NULL,
3303                 .enum_list      = NULL,
3304                 .flags          = FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT,
3305         },
3306         {
3307                 .label          = "browsable",
3308                 .type           = P_BOOL,
3309                 .p_class        = P_LOCAL,
3310                 .ptr            = &sDefault.bBrowseable,
3311                 .special        = NULL,
3312                 .enum_list      = NULL,
3313                 .flags          = FLAG_HIDE,
3314         },
3315         {
3316                 .label          = "enhanced browsing",
3317                 .type           = P_BOOL,
3318                 .p_class        = P_GLOBAL,
3319                 .ptr            = &Globals.enhanced_browsing,
3320                 .special        = NULL,
3321                 .enum_list      = NULL,
3322                 .flags          = FLAG_ADVANCED,
3323         },
3324
3325         {N_("WINS Options"), P_SEP, P_SEPARATOR},
3326
3327         {
3328                 .label          = "dns proxy",
3329                 .type           = P_BOOL,
3330                 .p_class        = P_GLOBAL,
3331                 .ptr            = &Globals.bDNSproxy,
3332                 .special        = NULL,
3333                 .enum_list      = NULL,
3334                 .flags          = FLAG_ADVANCED,
3335         },
3336         {
3337                 .label          = "wins proxy",
3338                 .type           = P_BOOL,
3339                 .p_class        = P_GLOBAL,
3340                 .ptr            = &Globals.bWINSproxy,
3341                 .special        = NULL,
3342                 .enum_list      = NULL,
3343                 .flags          = FLAG_ADVANCED,
3344         },
3345         {
3346                 .label          = "wins server",
3347                 .type           = P_LIST,
3348                 .p_class        = P_GLOBAL,
3349                 .ptr            = &Globals.szWINSservers,
3350                 .special        = NULL,
3351                 .enum_list      = NULL,
3352                 .flags          = FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD,
3353         },
3354         {
3355                 .label          = "wins support",
3356                 .type           = P_BOOL,
3357                 .p_class        = P_GLOBAL,
3358                 .ptr            = &Globals.bWINSsupport,
3359                 .special        = NULL,
3360                 .enum_list      = NULL,
3361                 .flags          = FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD,
3362         },
3363         {
3364                 .label          = "wins hook",
3365                 .type           = P_STRING,
3366                 .p_class        = P_GLOBAL,
3367                 .ptr            = &Globals.szWINSHook,
3368                 .special        = NULL,
3369                 .enum_list      = NULL,
3370                 .flags          = FLAG_ADVANCED,
3371         },
3372
3373         {N_("Locking Options"), P_SEP, P_SEPARATOR},
3374
3375         {
3376                 .label          = "blocking locks",
3377                 .type           = P_BOOL,
3378                 .p_class        = P_LOCAL,
3379                 .ptr            = &sDefault.bBlockingLocks,
3380                 .special        = NULL,
3381                 .enum_list      = NULL,
3382                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
3383         },
3384         {
3385                 .label          = "csc policy",
3386                 .type           = P_ENUM,
3387                 .p_class        = P_LOCAL,
3388                 .ptr            = &sDefault.iCSCPolicy,
3389                 .special        = NULL,
3390                 .enum_list      = enum_csc_policy,
3391                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
3392         },
3393         {
3394                 .label          = "fake oplocks",
3395                 .type           = P_BOOL,
3396                 .p_class        = P_LOCAL,
3397                 .ptr            = &sDefault.bFakeOplocks,
3398                 .special        = NULL,
3399                 .enum_list      = NULL,
3400                 .flags          = FLAG_ADVANCED | FLAG_SHARE,
3401         },
3402         {
3403                 .label          = "kernel oplocks",
3404                 .type           = P_BOOL,
3405                 .p_class        = P_GLOBAL,
3406                 .ptr            = &Globals.bKernelOplocks,
3407                 .special        = NULL,
3408                 .enum_list      = NULL,
3409                 .flags          = FLAG_ADVANCED | FLAG_GLOBAL,
3410         },
3411         {
3412                 .label          = "locking",
3413                 .type           = P_BOOL,
3414                 .p_class        = P_LOCAL,
3415                 .ptr            = &sDefault.bLocking,
3416                 .special        = NULL,
3417                 .enum_list      = NULL,
3418                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
3419         },
3420         {
3421                 .label          = "lock spin time",
3422                 .type           = P_INTEGER,
3423                 .p_class        = P_GLOBAL,
3424                 .ptr            = &Globals.iLockSpinTime,
3425                 .special        = NULL,
3426                 .enum_list      = NULL,
3427                 .flags          = FLAG_ADVANCED | FLAG_GLOBAL,
3428         },
3429         {
3430                 .label          = "oplocks",
3431                 .type           = P_BOOL,
3432                 .p_class        = P_LOCAL,
3433                 .ptr            = &sDefault.bOpLocks,
3434                 .special        = NULL,
3435                 .enum_list      = NULL,
3436                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
3437         },
3438         {
3439                 .label          = "level2 oplocks",
3440                 .type           = P_BOOL,
3441                 .p_class        = P_LOCAL,
3442                 .ptr            = &sDefault.bLevel2OpLocks,
3443                 .special        = NULL,
3444                 .enum_list      = NULL,
3445                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
3446         },
3447         {
3448                 .label          = "oplock break wait time",
3449                 .type           = P_INTEGER,
3450                 .p_class        = P_GLOBAL,
3451                 .ptr            = &Globals.oplock_break_wait_time,
3452                 .special        = NULL,
3453                 .enum_list      = NULL,
3454                 .flags          = FLAG_ADVANCED | FLAG_GLOBAL,
3455         },
3456         {
3457                 .label          = "oplock contention limit",
3458                 .type           = P_INTEGER,
3459                 .p_class        = P_LOCAL,
3460                 .ptr            = &sDefault.iOplockContentionLimit,
3461                 .special        = NULL,
3462                 .enum_list      = NULL,
3463                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
3464         },
3465         {
3466                 .label          = "posix locking",
3467                 .type           = P_BOOL,
3468                 .p_class        = P_LOCAL,
3469                 .ptr            = &sDefault.bPosixLocking,
3470                 .special        = NULL,
3471                 .enum_list      = NULL,
3472                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
3473         },
3474         {
3475                 .label          = "strict locking",
3476                 .type           = P_ENUM,
3477                 .p_class        = P_LOCAL,
3478                 .ptr            = &sDefault.iStrictLocking,
3479                 .special        = NULL,
3480                 .enum_list      = enum_bool_auto,
3481                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
3482         },
3483         {
3484                 .label          = "share modes",
3485                 .type           = P_BOOL,
3486                 .p_class        = P_LOCAL,
3487                 .ptr            = &sDefault.bShareModes,
3488                 .special        = NULL,
3489                 .enum_list      = NULL,
3490                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
3491         },
3492
3493         {N_("Ldap Options"), P_SEP, P_SEPARATOR},
3494
3495         {
3496                 .label          = "ldap admin dn",
3497                 .type           = P_STRING,
3498                 .p_class        = P_GLOBAL,
3499                 .ptr            = &Globals.szLdapAdminDn,
3500                 .special        = NULL,
3501                 .enum_list      = NULL,
3502                 .flags          = FLAG_ADVANCED,
3503         },
3504         {
3505                 .label          = "ldap delete dn",
3506                 .type           = P_BOOL,
3507                 .p_class        = P_GLOBAL,
3508                 .ptr            = &Globals.ldap_delete_dn,
3509                 .special        = NULL,
3510                 .enum_list      = NULL,
3511                 .flags          = FLAG_ADVANCED,
3512         },
3513         {
3514                 .label          = "ldap group suffix",
3515                 .type           = P_STRING,
3516                 .p_class        = P_GLOBAL,
3517                 .ptr            = &Globals.szLdapGroupSuffix,
3518                 .special        = NULL,
3519                 .enum_list      = NULL,
3520                 .flags          = FLAG_ADVANCED,
3521         },
3522         {
3523                 .label          = "ldap idmap suffix",
3524                 .type           = P_STRING,
3525                 .p_class        = P_GLOBAL,
3526                 .ptr            = &Globals.szLdapIdmapSuffix,
3527                 .special        = NULL,
3528                 .enum_list      = NULL,
3529                 .flags          = FLAG_ADVANCED,
3530         },
3531         {
3532                 .label          = "ldap machine suffix",
3533                 .type           = P_STRING,
3534                 .p_class        = P_GLOBAL,
3535                 .ptr            = &Globals.szLdapMachineSuffix,
3536                 .special        = NULL,
3537                 .enum_list      = NULL,
3538                 .flags          = FLAG_ADVANCED,
3539         },
3540         {
3541                 .label          = "ldap passwd sync",
3542                 .type           = P_ENUM,
3543                 .p_class        = P_GLOBAL,
3544                 .ptr            = &Globals.ldap_passwd_sync,
3545                 .special        = NULL,
3546                 .enum_list      = enum_ldap_passwd_sync,
3547                 .flags          = FLAG_ADVANCED,
3548         },
3549         {
3550                 .label          = "ldap password sync",
3551                 .type           = P_ENUM,
3552                 .p_class        = P_GLOBAL,
3553                 .ptr            = &Globals.ldap_passwd_sync,
3554                 .special        = NULL,
3555                 .enum_list      = enum_ldap_passwd_sync,
3556                 .flags          = FLAG_HIDE,
3557         },
3558         {
3559                 .label          = "ldap replication sleep",
3560                 .type           = P_INTEGER,
3561                 .p_class        = P_GLOBAL,
3562                 .ptr            = &Globals.ldap_replication_sleep,
3563                 .special        = NULL,
3564                 .enum_list      = NULL,
3565                 .flags          = FLAG_ADVANCED,
3566         },
3567         {
3568                 .label          = "ldap suffix",
3569                 .type           = P_STRING,
3570                 .p_class        = P_GLOBAL,
3571                 .ptr            = &Globals.szLdapSuffix,
3572                 .special        = NULL,
3573                 .enum_list      = NULL,
3574                 .flags          = FLAG_ADVANCED,
3575         },
3576         {
3577                 .label          = "ldap ssl",
3578                 .type           = P_ENUM,
3579                 .p_class        = P_GLOBAL,
3580                 .ptr            = &Globals.ldap_ssl,
3581                 .special        = NULL,
3582                 .enum_list      = enum_ldap_ssl,
3583                 .flags          = FLAG_ADVANCED,
3584         },
3585         {
3586                 .label          = "ldap timeout",
3587                 .type           = P_INTEGER,
3588                 .p_class        = P_GLOBAL,
3589                 .ptr            = &Globals.ldap_timeout,
3590                 .special        = NULL,
3591                 .enum_list      = NULL,
3592                 .flags          = FLAG_ADVANCED,
3593         },
3594         {
3595                 .label          = "ldap connection timeout",
3596                 .type           = P_INTEGER,
3597                 .p_class        = P_GLOBAL,
3598                 .ptr            = &Globals.ldap_connection_timeout,
3599                 .special        = NULL,
3600                 .enum_list      = NULL,
3601                 .flags          = FLAG_ADVANCED,
3602         },
3603         {
3604                 .label          = "ldap page size",
3605                 .type           = P_INTEGER,
3606                 .p_class        = P_GLOBAL,
3607                 .ptr            = &Globals.ldap_page_size,
3608                 .special        = NULL,
3609                 .enum_list      = NULL,
3610                 .flags          = FLAG_ADVANCED,
3611         },
3612         {
3613                 .label          = "ldap user suffix",
3614                 .type           = P_STRING,
3615                 .p_class        = P_GLOBAL,
3616                 .ptr            = &Globals.szLdapUserSuffix,
3617                 .special        = NULL,
3618                 .enum_list      = NULL,
3619                 .flags          = FLAG_ADVANCED,
3620         },
3621         {
3622                 .label          = "ldap debug level",
3623                 .type           = P_INTEGER,
3624                 .p_class        = P_GLOBAL,
3625                 .ptr            = &Globals.ldap_debug_level,
3626                 .special        = handle_ldap_debug_level,
3627                 .enum_list      = NULL,
3628                 .flags          = FLAG_ADVANCED,
3629         },
3630         {
3631                 .label          = "ldap debug threshold",
3632                 .type           = P_INTEGER,
3633                 .p_class        = P_GLOBAL,
3634                 .ptr            = &Globals.ldap_debug_threshold,
3635                 .special        = NULL,
3636                 .enum_list      = NULL,
3637                 .flags          = FLAG_ADVANCED,
3638         },
3639
3640         {N_("EventLog Options"), P_SEP, P_SEPARATOR},
3641
3642         {
3643                 .label          = "eventlog list",
3644                 .type           = P_LIST,
3645                 .p_class        = P_GLOBAL,
3646                 .ptr            = &Globals.szEventLogs,
3647                 .special        = NULL,
3648                 .enum_list      = NULL,
3649                 .flags          = FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE,
3650         },
3651
3652         {N_("Miscellaneous Options"), P_SEP, P_SEPARATOR},
3653
3654         {
3655                 .label          = "add share command",
3656                 .type           = P_STRING,
3657                 .p_class        = P_GLOBAL,
3658                 .ptr            = &Globals.szAddShareCommand,
3659                 .special        = NULL,
3660                 .enum_list      = NULL,
3661                 .flags          = FLAG_ADVANCED,
3662         },
3663         {
3664                 .label          = "change share command",
3665                 .type           = P_STRING,
3666                 .p_class        = P_GLOBAL,
3667                 .ptr            = &Globals.szChangeShareCommand,
3668                 .special        = NULL,
3669                 .enum_list      = NULL,
3670                 .flags          = FLAG_ADVANCED,
3671         },
3672         {
3673                 .label          = "delete share command",
3674                 .type           = P_STRING,
3675                 .p_class        = P_GLOBAL,
3676                 .ptr            = &Globals.szDeleteShareCommand,
3677                 .special        = NULL,
3678                 .enum_list      = NULL,
3679                 .flags          = FLAG_ADVANCED,
3680         },
3681         {
3682                 .label          = "config file",
3683                 .type           = P_STRING,
3684                 .p_class        = P_GLOBAL,
3685                 .ptr            = &Globals.szConfigFile,
3686                 .special        = NULL,
3687                 .enum_list      = NULL,
3688                 .flags          = FLAG_HIDE,
3689         },
3690         {
3691                 .label          = "preload",
3692                 .type           = P_STRING,
3693                 .p_class        = P_GLOBAL,
3694                 .ptr            = &Globals.szAutoServices,
3695                 .special        = NULL,
3696                 .enum_list      = NULL,
3697                 .flags          = FLAG_ADVANCED,
3698         },
3699         {
3700                 .label          = "auto services",
3701                 .type           = P_STRING,
3702                 .p_class        = P_GLOBAL,
3703                 .ptr            = &Globals.szAutoServices,
3704                 .special        = NULL,
3705                 .enum_list      = NULL,
3706                 .flags          = FLAG_ADVANCED,
3707         },
3708         {
3709                 .label          = "lock directory",
3710                 .type           = P_STRING,
3711                 .p_class        = P_GLOBAL,
3712                 .ptr            = &Globals.szLockDir,
3713                 .special        = NULL,
3714                 .enum_list      = NULL,
3715                 .flags          = FLAG_ADVANCED,
3716         },
3717         {
3718                 .label          = "lock dir",
3719                 .type           = P_STRING,
3720                 .p_class        = P_GLOBAL,
3721                 .ptr            = &Globals.szLockDir,
3722                 .special        = NULL,
3723                 .enum_list      = NULL,
3724                 .flags          = FLAG_HIDE,
3725         },
3726         {
3727                 .label          = "pid directory",
3728                 .type           = P_STRING,
3729                 .p_class        = P_GLOBAL,
3730                 .ptr            = &Globals.szPidDir,
3731                 .special        = NULL,
3732                 .enum_list      = NULL,
3733                 .flags          = FLAG_ADVANCED,
3734         },
3735 #ifdef WITH_UTMP
3736         {
3737                 .label          = "utmp directory",
3738                 .type           = P_STRING,
3739                 .p_class        = P_GLOBAL,
3740                 .ptr            = &Globals.szUtmpDir,
3741                 .special        = NULL,
3742                 .enum_list      = NULL,
3743                 .flags          = FLAG_ADVANCED,
3744         },
3745         {
3746                 .label          = "wtmp directory",
3747                 .type           = P_STRING,
3748                 .p_class        = P_GLOBAL,
3749                 .ptr            = &Globals.szWtmpDir,
3750                 .special        = NULL,
3751                 .enum_list      = NULL,
3752                 .flags          = FLAG_ADVANCED,
3753         },
3754         {
3755                 .label          = "utmp",
3756                 .type           = P_BOOL,
3757                 .p_class        = P_GLOBAL,
3758                 .ptr            = &Globals.bUtmp,
3759                 .special        = NULL,
3760                 .enum_list      = NULL,
3761                 .flags          = FLAG_ADVANCED,
3762         },
3763 #endif
3764         {
3765                 .label          = "default service",
3766                 .type           = P_STRING,
3767                 .p_class        = P_GLOBAL,
3768                 .ptr            = &Globals.szDefaultService,
3769                 .special        = NULL,
3770                 .enum_list      = NULL,
3771                 .flags          = FLAG_ADVANCED,
3772         },
3773         {
3774                 .label          = "default",
3775                 .type           = P_STRING,
3776                 .p_class        = P_GLOBAL,
3777                 .ptr            = &Globals.szDefaultService,
3778                 .special        = NULL,
3779                 .enum_list      = NULL,
3780                 .flags          = FLAG_ADVANCED,
3781         },
3782         {
3783                 .label          = "message command",
3784                 .type           = P_STRING,
3785                 .p_class        = P_GLOBAL,
3786                 .ptr            = &Globals.szMsgCommand,
3787                 .special        = NULL,
3788                 .enum_list      = NULL,
3789                 .flags          = FLAG_ADVANCED,
3790         },
3791         {
3792                 .label          = "dfree cache time",
3793                 .type           = P_INTEGER,
3794                 .p_class        = P_LOCAL,
3795                 .ptr            = &sDefault.iDfreeCacheTime,
3796                 .special        = NULL,
3797                 .enum_list      = NULL,
3798                 .flags          = FLAG_ADVANCED,
3799         },
3800         {
3801                 .label          = "dfree command",
3802                 .type           = P_STRING,
3803                 .p_class        = P_LOCAL,
3804                 .ptr            = &sDefault.szDfree,
3805                 .special        = NULL,
3806                 .enum_list      = NULL,
3807                 .flags          = FLAG_ADVANCED,
3808         },
3809         {
3810                 .label          = "get quota command",
3811                 .type           = P_STRING,
3812                 .p_class        = P_GLOBAL,
3813                 .ptr            = &Globals.szGetQuota,
3814                 .special        = NULL,
3815                 .enum_list      = NULL,
3816                 .flags          = FLAG_ADVANCED,
3817         },
3818         {
3819                 .label          = "set quota command",
3820                 .type           = P_STRING,
3821                 .p_class        = P_GLOBAL,
3822                 .ptr            = &Globals.szSetQuota,
3823                 .special        = NULL,
3824                 .enum_list      = NULL,
3825                 .flags          = FLAG_ADVANCED,
3826         },
3827         {
3828                 .label          = "remote announce",
3829                 .type           = P_STRING,
3830                 .p_class        = P_GLOBAL,
3831                 .ptr            = &Globals.szRemoteAnnounce,
3832                 .special        = NULL,
3833                 .enum_list      = NULL,
3834                 .flags          = FLAG_ADVANCED,
3835         },
3836         {
3837                 .label          = "remote browse sync",
3838                 .type           = P_STRING,
3839                 .p_class        = P_GLOBAL,
3840                 .ptr            = &Globals.szRemoteBrowseSync,
3841                 .special        = NULL,
3842                 .enum_list      = NULL,
3843                 .flags          = FLAG_ADVANCED,
3844         },
3845         {
3846                 .label          = "socket address",
3847                 .type           = P_STRING,
3848                 .p_class        = P_GLOBAL,
3849                 .ptr            = &Globals.szSocketAddress,
3850                 .special        = NULL,
3851                 .enum_list      = NULL,
3852                 .flags          = FLAG_ADVANCED,
3853         },
3854         {
3855                 .label          = "homedir map",
3856                 .type           = P_STRING,
3857                 .p_class        = P_GLOBAL,
3858                 .ptr            = &Globals.szNISHomeMapName,
3859                 .special        = NULL,
3860                 .enum_list      = NULL,
3861                 .flags          = FLAG_ADVANCED,
3862         },
3863         {
3864                 .label          = "afs username map",
3865                 .type           = P_STRING,
3866                 .p_class        = P_GLOBAL,
3867                 .ptr            = &Globals.szAfsUsernameMap,
3868                 .special        = NULL,
3869                 .enum_list      = NULL,
3870                 .flags          = FLAG_ADVANCED,
3871         },
3872         {
3873                 .label          = "afs token lifetime",
3874                 .type           = P_INTEGER,
3875                 .p_class        = P_GLOBAL,
3876                 .ptr            = &Globals.iAfsTokenLifetime,
3877                 .special        = NULL,
3878                 .enum_list      = NULL,
3879                 .flags          = FLAG_ADVANCED,
3880         },
3881         {
3882                 .label          = "log nt token command",
3883                 .type           = P_STRING,
3884                 .p_class        = P_GLOBAL,
3885                 .ptr            = &Globals.szLogNtTokenCommand,
3886                 .special        = NULL,
3887                 .enum_list      = NULL,
3888                 .flags          = FLAG_ADVANCED,
3889         },
3890         {
3891                 .label          = "time offset",
3892                 .type           = P_INTEGER,
3893                 .p_class        = P_GLOBAL,
3894                 .ptr            = &extra_time_offset,
3895                 .special        = NULL,
3896                 .enum_list      = NULL,
3897                 .flags          = FLAG_ADVANCED,
3898         },
3899         {
3900                 .label          = "NIS homedir",
3901                 .type           = P_BOOL,
3902                 .p_class        = P_GLOBAL,
3903                 .ptr            = &Globals.bNISHomeMap,
3904                 .special        = NULL,
3905                 .enum_list      = NULL,
3906                 .flags          = FLAG_ADVANCED,
3907         },
3908         {
3909                 .label          = "-valid",
3910                 .type           = P_BOOL,
3911                 .p_class        = P_LOCAL,
3912                 .ptr            = &sDefault.valid,
3913                 .special        = NULL,
3914                 .enum_list      = NULL,
3915                 .flags          = FLAG_HIDE,
3916         },
3917         {
3918                 .label          = "copy",
3919                 .type           = P_STRING,
3920                 .p_class        = P_LOCAL,
3921                 .ptr            = &sDefault.szCopy,
3922                 .special        = handle_copy,
3923                 .enum_list      = NULL,
3924                 .flags          = FLAG_HIDE,
3925         },
3926         {
3927                 .label          = "include",
3928                 .type           = P_STRING,
3929                 .p_class        = P_LOCAL,
3930                 .ptr            = &sDefault.szInclude,
3931                 .special        = handle_include,
3932                 .enum_list      = NULL,
3933                 .flags          = FLAG_HIDE,
3934         },
3935         {
3936                 .label          = "preexec",
3937                 .type           = P_STRING,
3938                 .p_class        = P_LOCAL,
3939                 .ptr            = &sDefault.szPreExec,
3940                 .special        = NULL,
3941                 .enum_list      = NULL,
3942                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT,
3943         },
3944         {
3945                 .label          = "exec",
3946                 .type           = P_STRING,
3947                 .p_class        = P_LOCAL,
3948                 .ptr            = &sDefault.szPreExec,
3949                 .special        = NULL,
3950                 .enum_list      = NULL,
3951                 .flags          = FLAG_ADVANCED,
3952         },
3953         {
3954                 .label          = "preexec close",
3955                 .type           = P_BOOL,
3956                 .p_class        = P_LOCAL,
3957                 .ptr            = &sDefault.bPreexecClose,
3958                 .special        = NULL,
3959                 .enum_list      = NULL,
3960                 .flags          = FLAG_ADVANCED | FLAG_SHARE,
3961         },
3962         {
3963                 .label          = "postexec",
3964                 .type           = P_STRING,
3965                 .p_class        = P_LOCAL,
3966                 .ptr            = &sDefault.szPostExec,
3967                 .special        = NULL,
3968                 .enum_list      = NULL,
3969                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT,
3970         },
3971         {
3972                 .label          = "root preexec",
3973                 .type           = P_STRING,
3974                 .p_class        = P_LOCAL,
3975                 .ptr            = &sDefault.szRootPreExec,
3976                 .special        = NULL,
3977                 .enum_list      = NULL,
3978                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT,
3979         },
3980         {
3981                 .label          = "root preexec close",
3982                 .type           = P_BOOL,
3983                 .p_class        = P_LOCAL,
3984                 .ptr            = &sDefault.bRootpreexecClose,
3985                 .special        = NULL,
3986                 .enum_list      = NULL,
3987                 .flags          = FLAG_ADVANCED | FLAG_SHARE,
3988         },
3989         {
3990                 .label          = "root postexec",
3991                 .type           = P_STRING,
3992                 .p_class        = P_LOCAL,
3993                 .ptr            = &sDefault.szRootPostExec,
3994                 .special        = NULL,
3995                 .enum_list      = NULL,
3996                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT,
3997         },
3998         {
3999                 .label          = "available",
4000                 .type           = P_BOOL,
4001                 .p_class        = P_LOCAL,
4002                 .ptr            = &sDefault.bAvailable,
4003                 .special        = NULL,
4004                 .enum_list      = NULL,
4005                 .flags          = FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT,
4006         },
4007         {
4008                 .label          = "registry shares",
4009                 .type           = P_BOOL,
4010                 .p_class        = P_GLOBAL,
4011                 .ptr            = &Globals.bRegistryShares,
4012                 .special        = NULL,
4013                 .enum_list      = NULL,
4014                 .flags          = FLAG_ADVANCED,
4015         },
4016         {
4017                 .label          = "usershare allow guests",
4018                 .type           = P_BOOL,
4019                 .p_class        = P_GLOBAL,
4020                 .ptr            = &Globals.bUsershareAllowGuests,
4021                 .special        = NULL,
4022                 .enum_list      = NULL,
4023                 .flags          = FLAG_ADVANCED,
4024         },
4025         {
4026                 .label          = "usershare max shares",
4027                 .type           = P_INTEGER,
4028                 .p_class        = P_GLOBAL,
4029                 .ptr            = &Globals.iUsershareMaxShares,
4030                 .special        = NULL,
4031                 .enum_list      = NULL,
4032                 .flags          = FLAG_ADVANCED,
4033         },
4034         {
4035                 .label          = "usershare owner only",
4036                 .type           = P_BOOL,
4037                 .p_class        = P_GLOBAL,
4038                 .ptr            = &Globals.bUsershareOwnerOnly,
4039                 .special        = NULL,
4040                 .enum_list      = NULL,
4041                 .flags          = FLAG_ADVANCED,
4042         },
4043         {
4044                 .label          = "usershare path",
4045                 .type           = P_STRING,
4046                 .p_class        = P_GLOBAL,
4047                 .ptr            = &Globals.szUsersharePath,
4048                 .special        = NULL,
4049                 .enum_list      = NULL,
4050                 .flags          = FLAG_ADVANCED,
4051         },
4052         {
4053                 .label          = "usershare prefix allow list",
4054                 .type           = P_LIST,
4055                 .p_class        = P_GLOBAL,
4056                 .ptr            = &Globals.szUsersharePrefixAllowList,
4057                 .special        = NULL,
4058                 .enum_list      = NULL,
4059                 .flags          = FLAG_ADVANCED,
4060         },
4061         {
4062                 .label          = "usershare prefix deny list",
4063                 .type           = P_LIST,
4064                 .p_class        = P_GLOBAL,
4065                 .ptr            = &Globals.szUsersharePrefixDenyList,
4066                 .special        = NULL,
4067                 .enum_list      = NULL,
4068                 .flags          = FLAG_ADVANCED,
4069         },
4070         {
4071                 .label          = "usershare template share",
4072                 .type           = P_STRING,
4073                 .p_class        = P_GLOBAL,
4074                 .ptr            = &Globals.szUsershareTemplateShare,
4075                 .special        = NULL,
4076                 .enum_list      = NULL,
4077                 .flags          = FLAG_ADVANCED,
4078         },
4079         {
4080                 .label          = "volume",
4081                 .type           = P_STRING,
4082                 .p_class        = P_LOCAL,
4083                 .ptr            = &sDefault.volume,
4084                 .special        = NULL,
4085                 .enum_list      = NULL,
4086                 .flags          = FLAG_ADVANCED | FLAG_SHARE,
4087         },
4088         {
4089                 .label          = "fstype",
4090                 .type           = P_STRING,
4091                 .p_class        = P_LOCAL,
4092                 .ptr            = &sDefault.fstype,
4093                 .special        = NULL,
4094                 .enum_list      = NULL,
4095                 .flags          = FLAG_ADVANCED | FLAG_SHARE,
4096         },
4097         {
4098                 .label          = "set directory",
4099                 .type           = P_BOOLREV,
4100                 .p_class        = P_LOCAL,
4101                 .ptr            = &sDefault.bNo_set_dir,
4102                 .special        = NULL,
4103                 .enum_list      = NULL,
4104                 .flags          = FLAG_ADVANCED | FLAG_SHARE,
4105         },
4106         {
4107                 .label          = "wide links",
4108                 .type           = P_BOOL,
4109                 .p_class        = P_LOCAL,
4110                 .ptr            = &sDefault.bWidelinks,
4111                 .special        = NULL,
4112                 .enum_list      = NULL,
4113                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
4114         },
4115         {
4116                 .label          = "follow symlinks",
4117                 .type           = P_BOOL,
4118                 .p_class        = P_LOCAL,
4119                 .ptr            = &sDefault.bSymlinks,
4120                 .special        = NULL,
4121                 .enum_list      = NULL,
4122                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
4123         },
4124         {
4125                 .label          = "dont descend",
4126                 .type           = P_STRING,
4127                 .p_class        = P_LOCAL,
4128                 .ptr            = &sDefault.szDontdescend,
4129                 .special        = NULL,
4130                 .enum_list      = NULL,
4131                 .flags          = FLAG_ADVANCED | FLAG_SHARE,
4132         },
4133         {
4134                 .label          = "magic script",
4135                 .type           = P_STRING,
4136                 .p_class        = P_LOCAL,
4137                 .ptr            = &sDefault.szMagicScript,
4138                 .special        = NULL,
4139                 .enum_list      = NULL,
4140                 .flags          = FLAG_ADVANCED | FLAG_SHARE,
4141         },
4142         {
4143                 .label          = "magic output",
4144                 .type           = P_STRING,
4145                 .p_class        = P_LOCAL,
4146                 .ptr            = &sDefault.szMagicOutput,
4147                 .special        = NULL,
4148                 .enum_list      = NULL,
4149                 .flags          = FLAG_ADVANCED | FLAG_SHARE,
4150         },
4151         {
4152                 .label          = "delete readonly",
4153                 .type           = P_BOOL,
4154                 .p_class        = P_LOCAL,
4155                 .ptr            = &sDefault.bDeleteReadonly,
4156                 .special        = NULL,
4157                 .enum_list      = NULL,
4158                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
4159         },
4160         {
4161                 .label          = "dos filemode",
4162                 .type           = P_BOOL,
4163                 .p_class        = P_LOCAL,
4164                 .ptr            = &sDefault.bDosFilemode,
4165                 .special        = NULL,
4166                 .enum_list      = NULL,
4167                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
4168         },
4169         {
4170                 .label          = "dos filetimes",
4171                 .type           = P_BOOL,
4172                 .p_class        = P_LOCAL,
4173                 .ptr            = &sDefault.bDosFiletimes,
4174                 .special        = NULL,
4175                 .enum_list      = NULL,
4176                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
4177         },
4178         {
4179                 .label          = "dos filetime resolution",
4180                 .type           = P_BOOL,
4181                 .p_class        = P_LOCAL,
4182                 .ptr            = &sDefault.bDosFiletimeResolution,
4183                 .special        = NULL,
4184                 .enum_list      = NULL,
4185                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
4186         },
4187         {
4188                 .label          = "fake directory create times",
4189                 .type           = P_BOOL,
4190                 .p_class        = P_LOCAL,
4191                 .ptr            = &sDefault.bFakeDirCreateTimes,
4192                 .special        = NULL,
4193                 .enum_list      = NULL,
4194                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
4195         },
4196         {
4197                 .label          = "panic action",
4198                 .type           = P_STRING,
4199                 .p_class        = P_GLOBAL,
4200                 .ptr            = &Globals.szPanicAction,
4201                 .special        = NULL,
4202                 .enum_list      = NULL,
4203                 .flags          = FLAG_ADVANCED,
4204         },
4205
4206         {N_("VFS module options"), P_SEP, P_SEPARATOR},
4207
4208         {
4209                 .label          = "vfs objects",
4210                 .type           = P_LIST,
4211                 .p_class        = P_LOCAL,
4212                 .ptr            = &sDefault.szVfsObjects,
4213                 .special        = NULL,
4214                 .enum_list      = NULL,
4215                 .flags          = FLAG_ADVANCED | FLAG_SHARE,
4216         },
4217         {
4218                 .label          = "vfs object",
4219                 .type           = P_LIST,
4220                 .p_class        = P_LOCAL,
4221                 .ptr            = &sDefault.szVfsObjects,
4222                 .special        = NULL,
4223                 .enum_list      = NULL,
4224                 .flags          = FLAG_HIDE,
4225         },
4226
4227
4228         {N_("MSDFS options"), P_SEP, P_SEPARATOR},
4229
4230         {
4231                 .label          = "msdfs root",
4232                 .type           = P_BOOL,
4233                 .p_class        = P_LOCAL,
4234                 .ptr            = &sDefault.bMSDfsRoot,
4235                 .special        = NULL,
4236                 .enum_list      = NULL,
4237                 .flags          = FLAG_ADVANCED | FLAG_SHARE,
4238         },
4239         {
4240                 .label          = "msdfs proxy",
4241                 .type           = P_STRING,
4242                 .p_class        = P_LOCAL,
4243                 .ptr            = &sDefault.szMSDfsProxy,
4244                 .special        = NULL,
4245                 .enum_list      = NULL,
4246                 .flags          = FLAG_ADVANCED | FLAG_SHARE,
4247         },
4248         {
4249                 .label          = "host msdfs",
4250                 .type           = P_BOOL,
4251                 .p_class        = P_GLOBAL,
4252                 .ptr            = &Globals.bHostMSDfs,
4253                 .special        = NULL,
4254                 .enum_list      = NULL,
4255                 .flags          = FLAG_ADVANCED,
4256         },
4257
4258         {N_("Winbind options"), P_SEP, P_SEPARATOR},
4259
4260         {
4261                 .label          = "passdb expand explicit",
4262                 .type           = P_BOOL,
4263                 .p_class        = P_GLOBAL,
4264                 .ptr            = &Globals.bPassdbExpandExplicit,
4265                 .special        = NULL,
4266                 .enum_list      = NULL,
4267                 .flags          = FLAG_ADVANCED,
4268         },
4269         {
4270                 .label          = "idmap backend",
4271                 .type           = P_STRING,
4272                 .p_class        = P_GLOBAL,
4273                 .ptr            = &Globals.szIdmapBackend,
4274                 .special        = NULL,
4275                 .enum_list      = NULL,
4276                 .flags          = FLAG_ADVANCED,
4277         },
4278         {
4279                 .label          = "idmap alloc backend",
4280                 .type           = P_STRING,
4281                 .p_class        = P_GLOBAL,
4282                 .ptr            = &Globals.szIdmapAllocBackend,
4283                 .special        = NULL,
4284                 .enum_list      = NULL,
4285                 .flags          = FLAG_ADVANCED,
4286         },
4287         {
4288                 .label          = "idmap cache time",
4289                 .type           = P_INTEGER,
4290                 .p_class        = P_GLOBAL,
4291                 .ptr            = &Globals.iIdmapCacheTime,
4292                 .special        = NULL,
4293                 .enum_list      = NULL,
4294                 .flags          = FLAG_ADVANCED,
4295         },
4296         {
4297                 .label          = "idmap negative cache time",
4298                 .type           = P_INTEGER,
4299                 .p_class        = P_GLOBAL,
4300                 .ptr            = &Globals.iIdmapNegativeCacheTime,
4301                 .special        = NULL,
4302                 .enum_list      = NULL,
4303                 .flags          = FLAG_ADVANCED,
4304         },
4305         {
4306                 .label          = "idmap uid",
4307                 .type           = P_STRING,
4308                 .p_class        = P_GLOBAL,
4309                 .ptr            = &Globals.szIdmapUID,
4310                 .special        = handle_idmap_uid,
4311                 .enum_list      = NULL,
4312                 .flags          = FLAG_ADVANCED,
4313         },
4314         {
4315                 .label          = "winbind uid",
4316                 .type           = P_STRING,
4317                 .p_class        = P_GLOBAL,
4318                 .ptr            = &Globals.szIdmapUID,
4319                 .special        = handle_idmap_uid,
4320                 .enum_list      = NULL,
4321                 .flags          = FLAG_HIDE,
4322         },
4323         {
4324                 .label          = "idmap gid",
4325                 .type           = P_STRING,
4326                 .p_class        = P_GLOBAL,
4327                 .ptr            = &Globals.szIdmapGID,
4328                 .special        = handle_idmap_gid,
4329                 .enum_list      = NULL,
4330                 .flags          = FLAG_ADVANCED,
4331         },
4332         {
4333                 .label          = "winbind gid",
4334                 .type           = P_STRING,
4335                 .p_class        = P_GLOBAL,
4336                 .ptr            = &Globals.szIdmapGID,
4337                 .special        = handle_idmap_gid,
4338                 .enum_list      = NULL,
4339                 .flags          = FLAG_HIDE,
4340         },
4341         {
4342                 .label          = "template homedir",
4343                 .type           = P_STRING,
4344                 .p_class        = P_GLOBAL,
4345                 .ptr            = &Globals.szTemplateHomedir,
4346                 .special        = NULL,
4347                 .enum_list      = NULL,
4348                 .flags          = FLAG_ADVANCED,
4349         },
4350         {
4351                 .label          = "template shell",
4352                 .type           = P_STRING,
4353                 .p_class        = P_GLOBAL,
4354                 .ptr            = &Globals.szTemplateShell,
4355                 .special        = NULL,
4356                 .enum_list      = NULL,
4357                 .flags          = FLAG_ADVANCED,
4358         },
4359         {
4360                 .label          = "winbind separator",
4361                 .type           = P_STRING,
4362                 .p_class        = P_GLOBAL,
4363                 .ptr            = &Globals.szWinbindSeparator,
4364                 .special        = NULL,
4365                 .enum_list      = NULL,
4366                 .flags          = FLAG_ADVANCED,
4367         },
4368         {
4369                 .label          = "winbind cache time",
4370                 .type           = P_INTEGER,
4371                 .p_class        = P_GLOBAL,
4372                 .ptr            = &Globals.winbind_cache_time,
4373                 .special        = NULL,
4374                 .enum_list      = NULL,
4375                 .flags          = FLAG_ADVANCED,
4376         },
4377         {
4378                 .label          = "winbind reconnect delay",
4379                 .type           = P_INTEGER,
4380                 .p_class        = P_GLOBAL,
4381                 .ptr            = &Globals.winbind_reconnect_delay,
4382                 .special        = NULL,
4383                 .enum_list      = NULL,
4384                 .flags          = FLAG_ADVANCED,
4385         },
4386         {
4387                 .label          = "winbind enum users",
4388                 .type           = P_BOOL,
4389                 .p_class        = P_GLOBAL,
4390                 .ptr            = &Globals.bWinbindEnumUsers,
4391                 .special        = NULL,
4392                 .enum_list      = NULL,
4393                 .flags          = FLAG_ADVANCED,
4394         },
4395         {
4396                 .label          = "winbind enum groups",
4397                 .type           = P_BOOL,
4398                 .p_class        = P_GLOBAL,
4399                 .ptr            = &Globals.bWinbindEnumGroups,
4400                 .special        = NULL,
4401                 .enum_list      = NULL,
4402                 .flags          = FLAG_ADVANCED,
4403         },
4404         {
4405                 .label          = "winbind use default domain",
4406                 .type           = P_BOOL,
4407                 .p_class        = P_GLOBAL,
4408                 .ptr            = &Globals.bWinbindUseDefaultDomain,
4409                 .special        = NULL,
4410                 .enum_list      = NULL,
4411                 .flags          = FLAG_ADVANCED,
4412         },
4413         {
4414                 .label          = "winbind trusted domains only",
4415                 .type           = P_BOOL,
4416                 .p_class        = P_GLOBAL,
4417                 .ptr            = &Globals.bWinbindTrustedDomainsOnly,
4418                 .special        = NULL,
4419                 .enum_list      = NULL,
4420                 .flags          = FLAG_ADVANCED,
4421         },
4422         {
4423                 .label          = "winbind nested groups",
4424                 .type           = P_BOOL,
4425                 .p_class        = P_GLOBAL,
4426                 .ptr            = &Globals.bWinbindNestedGroups,
4427                 .special        = NULL,
4428                 .enum_list      = NULL,
4429                 .flags          = FLAG_ADVANCED,
4430         },
4431         {
4432                 .label          = "winbind expand groups",
4433                 .type           = P_INTEGER,
4434                 .p_class        = P_GLOBAL,
4435                 .ptr            = &Globals.winbind_expand_groups,
4436                 .special        = NULL,
4437                 .enum_list      = NULL,
4438                 .flags          = FLAG_ADVANCED,
4439         },
4440         {
4441                 .label          = "winbind nss info",
4442                 .type           = P_LIST,
4443                 .p_class        = P_GLOBAL,
4444                 .ptr            = &Globals.szWinbindNssInfo,
4445                 .special        = NULL,
4446                 .enum_list      = NULL,
4447                 .flags          = FLAG_ADVANCED,
4448         },
4449         {
4450                 .label          = "winbind refresh tickets",
4451                 .type           = P_BOOL,
4452                 .p_class        = P_GLOBAL,
4453                 .ptr            = &Globals.bWinbindRefreshTickets,
4454                 .special        = NULL,
4455                 .enum_list      = NULL,
4456                 .flags          = FLAG_ADVANCED,
4457         },
4458         {
4459                 .label          = "winbind offline logon",
4460                 .type           = P_BOOL,
4461                 .p_class        = P_GLOBAL,
4462                 .ptr            = &Globals.bWinbindOfflineLogon,
4463                 .special        = NULL,
4464                 .enum_list      = NULL,
4465                 .flags          = FLAG_ADVANCED,
4466         },
4467         {
4468                 .label          = "winbind normalize names",
4469                 .type           = P_BOOL,
4470                 .p_class        = P_GLOBAL,
4471                 .ptr            = &Globals.bWinbindNormalizeNames,
4472                 .special        = NULL,
4473                 .enum_list      = NULL,
4474                 .flags          = FLAG_ADVANCED,
4475         },
4476         {
4477                 .label          = "winbind rpc only",
4478                 .type           = P_BOOL,
4479                 .p_class        = P_GLOBAL,
4480                 .ptr            = &Globals.bWinbindRpcOnly,
4481                 .special        = NULL,
4482                 .enum_list      = NULL,
4483                 .flags          = FLAG_ADVANCED,
4484         },
4485
4486         {NULL,  P_BOOL,  P_NONE,  NULL,  NULL,  NULL,  0}
4487 };
4488
4489 /***************************************************************************
4490  Initialise the sDefault parameter structure for the printer values.
4491 ***************************************************************************/
4492
4493 static void init_printer_values(struct service *pService)
4494 {
4495         /* choose defaults depending on the type of printing */
4496         switch (pService->iPrinting) {
4497                 case PRINT_BSD:
4498                 case PRINT_AIX:
4499                 case PRINT_LPRNT:
4500                 case PRINT_LPROS2:
4501                         string_set(&pService->szLpqcommand, "lpq -P'%p'");
4502                         string_set(&pService->szLprmcommand, "lprm -P'%p' %j");
4503                         string_set(&pService->szPrintcommand, "lpr -r -P'%p' %s");
4504                         break;
4505
4506                 case PRINT_LPRNG:
4507                 case PRINT_PLP:
4508                         string_set(&pService->szLpqcommand, "lpq -P'%p'");
4509                         string_set(&pService->szLprmcommand, "lprm -P'%p' %j");
4510                         string_set(&pService->szPrintcommand, "lpr -r -P'%p' %s");
4511                         string_set(&pService->szQueuepausecommand, "lpc stop '%p'");
4512                         string_set(&pService->szQueueresumecommand, "lpc start '%p'");
4513                         string_set(&pService->szLppausecommand, "lpc hold '%p' %j");
4514                         string_set(&pService->szLpresumecommand, "lpc release '%p' %j");
4515                         break;
4516
4517                 case PRINT_CUPS:
4518                 case PRINT_IPRINT:
4519 #ifdef HAVE_CUPS
4520                         /* set the lpq command to contain the destination printer
4521                            name only.  This is used by cups_queue_get() */
4522                         string_set(&pService->szLpqcommand, "%p");
4523                         string_set(&pService->szLprmcommand, "");
4524                         string_set(&pService->szPrintcommand, "");
4525                         string_set(&pService->szLppausecommand, "");
4526                         string_set(&pService->szLpresumecommand, "");
4527                         string_set(&pService->szQueuepausecommand, "");
4528                         string_set(&pService->szQueueresumecommand, "");
4529 #else
4530                         string_set(&pService->szLpqcommand, "lpq -P'%p'");
4531                         string_set(&pService->szLprmcommand, "lprm -P'%p' %j");
4532                         string_set(&pService->szPrintcommand, "lpr -P'%p' %s; rm %s");
4533                         string_set(&pService->szLppausecommand, "lp -i '%p-%j' -H hold");
4534                         string_set(&pService->szLpresumecommand, "lp -i '%p-%j' -H resume");
4535                         string_set(&pService->szQueuepausecommand, "disable '%p'");
4536                         string_set(&pService->szQueueresumecommand, "enable '%p'");
4537 #endif /* HAVE_CUPS */
4538                         break;
4539
4540                 case PRINT_SYSV:
4541                 case PRINT_HPUX:
4542                         string_set(&pService->szLpqcommand, "lpstat -o%p");
4543                         string_set(&pService->szLprmcommand, "cancel %p-%j");
4544                         string_set(&pService->szPrintcommand, "lp -c -d%p %s; rm %s");
4545                         string_set(&pService->szQueuepausecommand, "disable %p");
4546                         string_set(&pService->szQueueresumecommand, "enable %p");
4547 #ifndef HPUX
4548                         string_set(&pService->szLppausecommand, "lp -i %p-%j -H hold");
4549                         string_set(&pService->szLpresumecommand, "lp -i %p-%j -H resume");
4550 #endif /* HPUX */
4551                         break;
4552
4553                 case PRINT_QNX:
4554                         string_set(&pService->szLpqcommand, "lpq -P%p");
4555                         string_set(&pService->szLprmcommand, "lprm -P%p %j");
4556                         string_set(&pService->szPrintcommand, "lp -r -P%p %s");
4557                         break;
4558
4559 #ifdef DEVELOPER
4560         case PRINT_TEST:
4561         case PRINT_VLP:
4562                 string_set(&pService->szPrintcommand, "vlp print %p %s");
4563                 string_set(&pService->szLpqcommand, "vlp lpq %p");
4564                 string_set(&pService->szLprmcommand, "vlp lprm %p %j");
4565                 string_set(&pService->szLppausecommand, "vlp lppause %p %j");
4566                 string_set(&pService->szLpresumecommand, "vlp lpresum %p %j");
4567                 string_set(&pService->szQueuepausecommand, "vlp queuepause %p");
4568                 string_set(&pService->szQueueresumecommand, "vlp queueresume %p");
4569                 break;
4570 #endif /* DEVELOPER */
4571
4572         }
4573 }
4574
4575 /**
4576  * Free the allocated data for one parameter for a given share.
4577  */
4578 static void free_parameter(int snum, struct parm_struct parm)
4579 {
4580         void *parm_ptr;
4581
4582         if (parm.ptr == NULL); {
4583                 return;
4584         }
4585
4586         if (snum < 0) {
4587                 parm_ptr = parm.ptr;
4588         } else if (parm.p_class != P_LOCAL) {
4589                 return;
4590         } else {
4591                 parm_ptr = lp_local_ptr(snum, parm.ptr);
4592         }
4593
4594         if ((parm.type == P_STRING) ||
4595             (parm.type == P_USTRING))
4596         {
4597                 string_free((char**)parm_ptr);
4598         } else if (parm.type == P_LIST) {
4599                 TALLOC_FREE(*((char***)parm_ptr));
4600         }
4601 }
4602
4603 /**
4604  * Free the allocated parameter data for a share.
4605  */
4606 static void free_parameters(int snum)
4607 {
4608         uint32_t i;
4609
4610         for (i=0; parm_table[i].label; i++) {
4611                 free_parameter(snum, parm_table[i]);
4612         }
4613 }
4614
4615 /**
4616  * Free the allocated global parameters.
4617  */
4618 static void free_global_parameters(void)
4619 {
4620         free_parameters(GLOBAL_SECTION_SNUM);
4621 }
4622
4623 /***************************************************************************
4624  Initialise the global parameter structure.
4625 ***************************************************************************/
4626
4627 static void init_globals(bool first_time_only)
4628 {
4629         static bool done_init = False;
4630         char *s = NULL;
4631         int i;
4632
4633         /* If requested to initialize only once and we've already done it... */
4634         if (first_time_only && done_init) {
4635                 /* ... then we have nothing more to do */
4636                 return;
4637         }
4638
4639         if (!done_init) {
4640                 /* The logfile can be set before this is invoked. Free it if so. */
4641                 if (Globals.szLogFile != NULL) {
4642                         string_free(&Globals.szLogFile);
4643                         Globals.szLogFile = NULL;
4644                 }
4645                 done_init = True;
4646         } else {
4647                 free_global_parameters();
4648         }
4649
4650         memset((void *)&Globals, '\0', sizeof(Globals));
4651
4652         for (i = 0; parm_table[i].label; i++) {
4653                 if ((parm_table[i].type == P_STRING ||
4654                      parm_table[i].type == P_USTRING) &&
4655                     parm_table[i].ptr)
4656                 {
4657                         string_set((char **)parm_table[i].ptr, "");
4658                 }
4659         }
4660
4661         string_set(&sDefault.fstype, FSTYPE_STRING);
4662         string_set(&sDefault.szPrintjobUsername, "%U");
4663
4664         init_printer_values(&sDefault);
4665
4666
4667         DEBUG(3, ("Initialising global parameters\n"));
4668
4669         string_set(&Globals.szSMBPasswdFile, get_dyn_SMB_PASSWD_FILE());
4670         string_set(&Globals.szPrivateDir, get_dyn_PRIVATE_DIR());
4671
4672         /* use the new 'hash2' method by default, with a prefix of 1 */
4673         string_set(&Globals.szManglingMethod, "hash2");
4674         Globals.mangle_prefix = 1;
4675
4676         string_set(&Globals.szGuestaccount, GUEST_ACCOUNT);
4677
4678         /* using UTF8 by default allows us to support all chars */
4679         string_set(&Globals.unix_charset, DEFAULT_UNIX_CHARSET);
4680
4681 #if defined(HAVE_NL_LANGINFO) && defined(CODESET)
4682         /* If the system supports nl_langinfo(), try to grab the value
4683            from the user's locale */
4684         string_set(&Globals.display_charset, "LOCALE");
4685 #else
4686         string_set(&Globals.display_charset, DEFAULT_DISPLAY_CHARSET);
4687 #endif
4688
4689         /* Use codepage 850 as a default for the dos character set */
4690         string_set(&Globals.dos_charset, DEFAULT_DOS_CHARSET);
4691
4692         /*
4693          * Allow the default PASSWD_CHAT to be overridden in local.h.
4694          */
4695         string_set(&Globals.szPasswdChat, DEFAULT_PASSWD_CHAT);
4696
4697         set_global_myname(myhostname());
4698         string_set(&Globals.szNetbiosName,global_myname());
4699
4700         set_global_myworkgroup(WORKGROUP);
4701         string_set(&Globals.szWorkgroup, lp_workgroup());
4702
4703         string_set(&Globals.szPasswdProgram, "");
4704         string_set(&Globals.szPidDir, get_dyn_PIDDIR());
4705         string_set(&Globals.szLockDir, get_dyn_LOCKDIR());
4706         string_set(&Globals.szSocketAddress, "0.0.0.0");
4707
4708         if (asprintf(&s, "Samba %s", SAMBA_VERSION_STRING) < 0) {
4709                 smb_panic("init_globals: ENOMEM");
4710         }
4711         string_set(&Globals.szServerString, s);
4712         SAFE_FREE(s);
4713         if (asprintf(&s, "%d.%d", DEFAULT_MAJOR_VERSION,
4714                         DEFAULT_MINOR_VERSION) < 0) {
4715                 smb_panic("init_globals: ENOMEM");
4716         }
4717         string_set(&Globals.szAnnounceVersion, s);
4718         SAFE_FREE(s);
4719 #ifdef DEVELOPER
4720         string_set(&Globals.szPanicAction, "/bin/sleep 999999999");
4721 #endif
4722
4723         string_set(&Globals.szSocketOptions, DEFAULT_SOCKET_OPTIONS);
4724
4725         string_set(&Globals.szLogonDrive, "");
4726         /* %N is the NIS auto.home server if -DAUTOHOME is used, else same as %L */
4727         string_set(&Globals.szLogonHome, "\\\\%N\\%U");
4728         string_set(&Globals.szLogonPath, "\\\\%N\\%U\\profile");
4729
4730         string_set(&Globals.szNameResolveOrder, "lmhosts wins host bcast");
4731         string_set(&Globals.szPasswordServer, "*");
4732
4733         Globals.AlgorithmicRidBase = BASE_RID;
4734
4735         Globals.bLoadPrinters = True;
4736         Globals.PrintcapCacheTime = 750;        /* 12.5 minutes */
4737
4738         Globals.ConfigBackend = config_backend;
4739
4740         /* Was 65535 (0xFFFF). 0x4101 matches W2K and causes major speed improvements... */
4741         /* Discovered by 2 days of pain by Don McCall @ HP :-). */
4742         Globals.max_xmit = 0x4104;
4743         Globals.max_mux = 50;   /* This is *needed* for profile support. */
4744         Globals.lpqcachetime = 30;      /* changed to handle large print servers better -- jerry */
4745         Globals.bDisableSpoolss = False;
4746         Globals.iMaxSmbdProcesses = 0;/* no limit specified */
4747         Globals.pwordlevel = 0;
4748         Globals.unamelevel = 0;
4749         Globals.deadtime = 0;
4750         Globals.getwd_cache = true;
4751         Globals.bLargeReadwrite = True;
4752         Globals.max_log_size = 5000;
4753         Globals.max_open_files = MAX_OPEN_FILES;
4754         Globals.open_files_db_hash_size = SMB_OPEN_DATABASE_TDB_HASH_SIZE;
4755         Globals.maxprotocol = PROTOCOL_NT1;
4756         Globals.minprotocol = PROTOCOL_CORE;
4757         Globals.security = SEC_USER;
4758         Globals.paranoid_server_security = True;
4759         Globals.bEncryptPasswords = True;
4760         Globals.bUpdateEncrypt = False;
4761         Globals.clientSchannel = Auto;
4762         Globals.serverSchannel = Auto;
4763         Globals.bReadRaw = True;
4764         Globals.bWriteRaw = True;
4765         Globals.bNullPasswords = False;
4766         Globals.bObeyPamRestrictions = False;
4767         Globals.syslog = 1;
4768         Globals.bSyslogOnly = False;
4769         Globals.bTimestampLogs = True;
4770         string_set(&Globals.szLogLevel, "0");
4771         Globals.bDebugPrefixTimestamp = False;
4772         Globals.bDebugHiresTimestamp = False;
4773         Globals.bDebugPid = False;
4774         Globals.bDebugUid = False;
4775         Globals.bDebugClass = False;
4776         Globals.bEnableCoreFiles = True;
4777         Globals.max_ttl = 60 * 60 * 24 * 3;     /* 3 days default. */
4778         Globals.max_wins_ttl = 60 * 60 * 24 * 6;        /* 6 days default. */
4779         Globals.min_wins_ttl = 60 * 60 * 6;     /* 6 hours default. */
4780         Globals.machine_password_timeout = 60 * 60 * 24 * 7;    /* 7 days default. */
4781         Globals.lm_announce = 2;        /* = Auto: send only if LM clients found */
4782         Globals.lm_interval = 60;
4783         Globals.announce_as = ANNOUNCE_AS_NT_SERVER;
4784 #if (defined(HAVE_NETGROUP) && defined(WITH_AUTOMOUNT))
4785         Globals.bNISHomeMap = False;
4786 #ifdef WITH_NISPLUS_HOME
4787         string_set(&Globals.szNISHomeMapName, "auto_home.org_dir");
4788 #else
4789         string_set(&Globals.szNISHomeMapName, "auto.home");
4790 #endif
4791 #endif
4792         Globals.bTimeServer = False;
4793         Globals.bBindInterfacesOnly = False;
4794         Globals.bUnixPasswdSync = False;
4795         Globals.bPamPasswordChange = False;
4796         Globals.bPasswdChatDebug = False;
4797         Globals.iPasswdChatTimeout = 2; /* 2 second default. */
4798         Globals.bNTPipeSupport = True;  /* Do NT pipes by default. */
4799         Globals.bNTStatusSupport = True; /* Use NT status by default. */
4800         Globals.bStatCache = True;      /* use stat cache by default */
4801         Globals.iMaxStatCacheSize = 256; /* 256k by default */
4802         Globals.restrict_anonymous = 0;
4803         Globals.bClientLanManAuth = False;      /* Do NOT use the LanMan hash if it is available */
4804         Globals.bClientPlaintextAuth = False;   /* Do NOT use a plaintext password even if is requested by the server */
4805         Globals.bLanmanAuth = False;    /* Do NOT use the LanMan hash, even if it is supplied */
4806         Globals.bNTLMAuth = True;       /* Do use NTLMv1 if it is supplied by the client (otherwise NTLMv2) */
4807         Globals.bClientNTLMv2Auth = False; /* Client should not use NTLMv2, as we can't tell that the server supports it. */
4808         /* Note, that we will use NTLM2 session security (which is different), if it is available */
4809
4810         Globals.map_to_guest = 0;       /* By Default, "Never" */
4811         Globals.oplock_break_wait_time = 0;     /* By Default, 0 msecs. */
4812         Globals.enhanced_browsing = true;
4813         Globals.iLockSpinTime = WINDOWS_MINIMUM_LOCK_TIMEOUT_MS; /* msec. */
4814 #ifdef MMAP_BLACKLIST
4815         Globals.bUseMmap = False;
4816 #else
4817         Globals.bUseMmap = True;
4818 #endif
4819         Globals.bUnixExtensions = True;
4820         Globals.bResetOnZeroVC = False;
4821
4822         /* hostname lookups can be very expensive and are broken on
4823            a large number of sites (tridge) */
4824         Globals.bHostnameLookups = False;
4825
4826         string_set(&Globals.szPassdbBackend, "smbpasswd");
4827         string_set(&Globals.szLdapSuffix, "");
4828         string_set(&Globals.szLdapMachineSuffix, "");
4829         string_set(&Globals.szLdapUserSuffix, "");
4830         string_set(&Globals.szLdapGroupSuffix, "");
4831         string_set(&Globals.szLdapIdmapSuffix, "");
4832
4833         string_set(&Globals.szLdapAdminDn, "");
4834         Globals.ldap_ssl = LDAP_SSL_ON;
4835         Globals.ldap_passwd_sync = LDAP_PASSWD_SYNC_OFF;
4836         Globals.ldap_delete_dn = False;
4837         Globals.ldap_replication_sleep = 1000; /* wait 1 sec for replication */
4838         Globals.ldap_timeout = LDAP_DEFAULT_TIMEOUT;
4839         Globals.ldap_connection_timeout = LDAP_CONNECTION_DEFAULT_TIMEOUT;
4840         Globals.ldap_page_size = LDAP_PAGE_SIZE;
4841
4842         Globals.ldap_debug_level = 0;
4843         Globals.ldap_debug_threshold = 10;
4844
4845         /* This is what we tell the afs client. in reality we set the token 
4846          * to never expire, though, when this runs out the afs client will 
4847          * forget the token. Set to 0 to get NEVERDATE.*/
4848         Globals.iAfsTokenLifetime = 604800;
4849         Globals.cups_connection_timeout = CUPS_DEFAULT_CONNECTION_TIMEOUT;
4850
4851 /* these parameters are set to defaults that are more appropriate
4852    for the increasing samba install base:
4853
4854    as a member of the workgroup, that will possibly become a
4855    _local_ master browser (lm = True).  this is opposed to a forced
4856    local master browser startup (pm = True).
4857
4858    doesn't provide WINS server service by default (wsupp = False),
4859    and doesn't provide domain master browser services by default, either.
4860
4861 */
4862
4863         Globals.bMsAddPrinterWizard = True;
4864         Globals.os_level = 20;
4865         Globals.bLocalMaster = True;
4866         Globals.iDomainMaster = Auto;   /* depending on bDomainLogons */
4867         Globals.bDomainLogons = False;
4868         Globals.bBrowseList = True;
4869         Globals.bWINSsupport = False;
4870         Globals.bWINSproxy = False;
4871
4872         TALLOC_FREE(Globals.szInitLogonDelayedHosts);
4873         Globals.InitLogonDelay = 100; /* 100 ms default delay */
4874
4875         Globals.bDNSproxy = True;
4876
4877         /* this just means to use them if they exist */
4878         Globals.bKernelOplocks = True;
4879
4880         Globals.bAllowTrustedDomains = True;
4881         string_set(&Globals.szIdmapBackend, "tdb");
4882
4883         string_set(&Globals.szTemplateShell, "/bin/false");
4884         string_set(&Globals.szTemplateHomedir, "/home/%D/%U");
4885         string_set(&Globals.szWinbindSeparator, "\\");
4886
4887         string_set(&Globals.szCupsServer, "");
4888         string_set(&Globals.szIPrintServer, "");
4889
4890         string_set(&Globals.ctdbdSocket, "");
4891         Globals.szClusterAddresses = NULL;
4892         Globals.clustering = False;
4893
4894         Globals.winbind_cache_time = 300;       /* 5 minutes */
4895         Globals.winbind_reconnect_delay = 30;   /* 30 seconds */
4896         Globals.bWinbindEnumUsers = False;
4897         Globals.bWinbindEnumGroups = False;
4898         Globals.bWinbindUseDefaultDomain = False;
4899         Globals.bWinbindTrustedDomainsOnly = False;
4900         Globals.bWinbindNestedGroups = True;
4901         Globals.winbind_expand_groups = 1;
4902         Globals.szWinbindNssInfo = str_list_make(NULL, "template", NULL);
4903         Globals.bWinbindRefreshTickets = False;
4904         Globals.bWinbindOfflineLogon = False;
4905
4906         Globals.iIdmapCacheTime = 86400 * 7; /* a week by default */
4907         Globals.iIdmapNegativeCacheTime = 120; /* 2 minutes by default */
4908
4909         Globals.bPassdbExpandExplicit = False;
4910
4911         Globals.name_cache_timeout = 660; /* In seconds */
4912
4913         Globals.bUseSpnego = True;
4914         Globals.bClientUseSpnego = True;
4915
4916         Globals.client_signing = Auto;
4917         Globals.server_signing = False;
4918
4919         Globals.bDeferSharingViolations = True;
4920         string_set(&Globals.smb_ports, SMB_PORTS);
4921
4922         Globals.bEnablePrivileges = True;
4923         Globals.bHostMSDfs        = True;
4924         Globals.bASUSupport       = False;
4925
4926         /* User defined shares. */
4927         if (asprintf(&s, "%s/usershares", get_dyn_STATEDIR()) < 0) {
4928                 smb_panic("init_globals: ENOMEM");
4929         }
4930         string_set(&Globals.szUsersharePath, s);
4931         SAFE_FREE(s);
4932         string_set(&Globals.szUsershareTemplateShare, "");
4933         Globals.iUsershareMaxShares = 0;
4934         /* By default disallow sharing of directories not owned by the sharer. */
4935         Globals.bUsershareOwnerOnly = True;
4936         /* By default disallow guest access to usershares. */
4937         Globals.bUsershareAllowGuests = False;
4938
4939         Globals.iKeepalive = DEFAULT_KEEPALIVE;
4940
4941         /* By default no shares out of the registry */
4942         Globals.bRegistryShares = False;
4943
4944         Globals.iminreceivefile = 0;
4945 }
4946
4947 /*******************************************************************
4948  Convenience routine to grab string parameters into temporary memory
4949  and run standard_sub_basic on them. The buffers can be written to by
4950  callers without affecting the source string.
4951 ********************************************************************/
4952
4953 static char *lp_string(const char *s)
4954 {
4955         char *ret;
4956         TALLOC_CTX *ctx = talloc_tos();
4957
4958         /* The follow debug is useful for tracking down memory problems
4959            especially if you have an inner loop that is calling a lp_*()
4960            function that returns a string.  Perhaps this debug should be
4961            present all the time? */
4962
4963 #if 0
4964         DEBUG(10, ("lp_string(%s)\n", s));
4965 #endif
4966
4967         ret = talloc_sub_basic(ctx,
4968                         get_current_username(),
4969                         current_user_info.domain,
4970                         s);
4971         if (trim_char(ret, '\"', '\"')) {
4972                 if (strchr(ret,'\"') != NULL) {
4973                         TALLOC_FREE(ret);
4974                         ret = talloc_sub_basic(ctx,
4975                                         get_current_username(),
4976                                         current_user_info.domain,
4977                                         s);
4978                 }
4979         }
4980         return ret;
4981 }
4982
4983 /*
4984    In this section all the functions that are used to access the 
4985    parameters from the rest of the program are defined 
4986 */
4987
4988 #define FN_GLOBAL_STRING(fn_name,ptr) \
4989  char *fn_name(void) {return(lp_string(*(char **)(ptr) ? *(char **)(ptr) : ""));}
4990 #define FN_GLOBAL_CONST_STRING(fn_name,ptr) \
4991  const char *fn_name(void) {return(*(const char **)(ptr) ? *(const char **)(ptr) : "");}
4992 #define FN_GLOBAL_LIST(fn_name,ptr) \
4993  const char **fn_name(void) {return(*(const char ***)(ptr));}
4994 #define FN_GLOBAL_BOOL(fn_name,ptr) \
4995  bool fn_name(void) {return(*(bool *)(ptr));}
4996 #define FN_GLOBAL_CHAR(fn_name,ptr) \
4997  char fn_name(void) {return(*(char *)(ptr));}
4998 #define FN_GLOBAL_INTEGER(fn_name,ptr) \
4999  int fn_name(void) {return(*(int *)(ptr));}
5000
5001 #define FN_LOCAL_STRING(fn_name,val) \
5002  char *fn_name(int i) {return(lp_string((LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val));}
5003 #define FN_LOCAL_CONST_STRING(fn_name,val) \
5004  const char *fn_name(int i) {return (const char *)((LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val);}
5005 #define FN_LOCAL_LIST(fn_name,val) \
5006  const char **fn_name(int i) {return(const char **)(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
5007 #define FN_LOCAL_BOOL(fn_name,val) \
5008  bool fn_name(int i) {return(bool)(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
5009 #define FN_LOCAL_INTEGER(fn_name,val) \
5010  int fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
5011
5012 #define FN_LOCAL_PARM_BOOL(fn_name,val) \
5013  bool fn_name(const struct share_params *p) {return(bool)(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
5014 #define FN_LOCAL_PARM_INTEGER(fn_name,val) \
5015  int fn_name(const struct share_params *p) {return(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
5016 #define FN_LOCAL_PARM_STRING(fn_name,val) \
5017  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));}
5018 #define FN_LOCAL_CHAR(fn_name,val) \
5019  char fn_name(const struct share_params *p) {return(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
5020
5021 FN_GLOBAL_STRING(lp_smb_ports, &Globals.smb_ports)
5022 FN_GLOBAL_STRING(lp_dos_charset, &Globals.dos_charset)
5023 FN_GLOBAL_STRING(lp_unix_charset, &Globals.unix_charset)
5024 FN_GLOBAL_STRING(lp_display_charset, &Globals.display_charset)
5025 FN_GLOBAL_STRING(lp_logfile, &Globals.szLogFile)
5026 FN_GLOBAL_STRING(lp_configfile, &Globals.szConfigFile)
5027 FN_GLOBAL_STRING(lp_smb_passwd_file, &Globals.szSMBPasswdFile)
5028 FN_GLOBAL_STRING(lp_private_dir, &Globals.szPrivateDir)
5029 FN_GLOBAL_STRING(lp_serverstring, &Globals.szServerString)
5030 FN_GLOBAL_INTEGER(lp_printcap_cache_time, &Globals.PrintcapCacheTime)
5031 FN_GLOBAL_STRING(lp_addport_cmd, &Globals.szAddPortCommand)
5032 FN_GLOBAL_STRING(lp_enumports_cmd, &Globals.szEnumPortsCommand)
5033 FN_GLOBAL_STRING(lp_addprinter_cmd, &Globals.szAddPrinterCommand)
5034 FN_GLOBAL_STRING(lp_deleteprinter_cmd, &Globals.szDeletePrinterCommand)
5035 FN_GLOBAL_STRING(lp_os2_driver_map, &Globals.szOs2DriverMap)
5036 FN_GLOBAL_STRING(lp_lockdir, &Globals.szLockDir)
5037 FN_GLOBAL_STRING(lp_piddir, &Globals.szPidDir)
5038 FN_GLOBAL_STRING(lp_mangling_method, &Globals.szManglingMethod)
5039 FN_GLOBAL_INTEGER(lp_mangle_prefix, &Globals.mangle_prefix)
5040 FN_GLOBAL_STRING(lp_utmpdir, &Globals.szUtmpDir)
5041 FN_GLOBAL_STRING(lp_wtmpdir, &Globals.szWtmpDir)
5042 FN_GLOBAL_BOOL(lp_utmp, &Globals.bUtmp)
5043 FN_GLOBAL_STRING(lp_rootdir, &Globals.szRootdir)
5044 FN_GLOBAL_STRING(lp_defaultservice, &Globals.szDefaultService)
5045 FN_GLOBAL_STRING(lp_msg_command, &Globals.szMsgCommand)
5046 FN_GLOBAL_STRING(lp_get_quota_command, &Globals.szGetQuota)
5047 FN_GLOBAL_STRING(lp_set_quota_command, &Globals.szSetQuota)
5048 FN_GLOBAL_STRING(lp_auto_services, &Globals.szAutoServices)
5049 FN_GLOBAL_STRING(lp_passwd_program, &Globals.szPasswdProgram)
5050 FN_GLOBAL_STRING(lp_passwd_chat, &Globals.szPasswdChat)
5051 FN_GLOBAL_STRING(lp_passwordserver, &Globals.szPasswordServer)
5052 FN_GLOBAL_STRING(lp_name_resolve_order, &Globals.szNameResolveOrder)
5053 FN_GLOBAL_STRING(lp_realm, &Globals.szRealm)
5054 FN_GLOBAL_CONST_STRING(lp_afs_username_map, &Globals.szAfsUsernameMap)
5055 FN_GLOBAL_INTEGER(lp_afs_token_lifetime, &Globals.iAfsTokenLifetime)
5056 FN_GLOBAL_STRING(lp_log_nt_token_command, &Globals.szLogNtTokenCommand)
5057 FN_GLOBAL_STRING(lp_username_map, &Globals.szUsernameMap)
5058 FN_GLOBAL_CONST_STRING(lp_logon_script, &Globals.szLogonScript)
5059 FN_GLOBAL_CONST_STRING(lp_logon_path, &Globals.szLogonPath)
5060 FN_GLOBAL_CONST_STRING(lp_logon_drive, &Globals.szLogonDrive)
5061 FN_GLOBAL_CONST_STRING(lp_logon_home, &Globals.szLogonHome)
5062 FN_GLOBAL_STRING(lp_remote_announce, &Globals.szRemoteAnnounce)
5063 FN_GLOBAL_STRING(lp_remote_browse_sync, &Globals.szRemoteBrowseSync)
5064 FN_GLOBAL_LIST(lp_wins_server_list, &Globals.szWINSservers)
5065 FN_GLOBAL_LIST(lp_interfaces, &Globals.szInterfaces)
5066 FN_GLOBAL_STRING(lp_socket_address, &Globals.szSocketAddress)
5067 FN_GLOBAL_STRING(lp_nis_home_map_name, &Globals.szNISHomeMapName)
5068 static FN_GLOBAL_STRING(lp_announce_version, &Globals.szAnnounceVersion)
5069 FN_GLOBAL_LIST(lp_netbios_aliases, &Globals.szNetbiosAliases)
5070 /* FN_GLOBAL_STRING(lp_passdb_backend, &Globals.szPassdbBackend)
5071  * lp_passdb_backend() should be replace by the this macro again after
5072  * some releases.
5073  * */
5074 const char *lp_passdb_backend(void)
5075 {
5076         char *delim, *quote;
5077
5078         delim = strchr( Globals.szPassdbBackend, ' ');
5079         /* no space at all */
5080         if (delim == NULL) {
5081                 goto out;
5082         }
5083
5084         quote = strchr(Globals.szPassdbBackend, '"');
5085         /* no quote char or non in the first part */
5086         if (quote == NULL || quote > delim) {
5087                 *delim = '\0';
5088                 goto warn;
5089         }
5090
5091         quote = strchr(quote+1, '"');
5092         if (quote == NULL) {
5093                 DEBUG(0, ("WARNING: Your 'passdb backend' configuration is invalid due to a missing second \" char.\n"));
5094                 goto out;
5095         } else if (*(quote+1) == '\0') {
5096                 /* space, fitting quote char, and one backend only */
5097                 goto out;
5098         } else {
5099                 /* terminate string after the fitting quote char */
5100                 *(quote+1) = '\0';
5101         }
5102
5103 warn:
5104         DEBUG(0, ("WARNING: Your 'passdb backend' configuration includes multiple backends.  This\n"
5105                 "is deprecated since Samba 3.0.23.  Please check WHATSNEW.txt or the section 'Passdb\n"
5106                 "Changes' from the ChangeNotes as part of the Samba HOWTO collection.  Only the first\n"
5107                 "backend (%s) is used.  The rest is ignored.\n", Globals.szPassdbBackend));
5108
5109 out:
5110         return Globals.szPassdbBackend;
5111 }
5112 FN_GLOBAL_LIST(lp_preload_modules, &Globals.szPreloadModules)
5113 FN_GLOBAL_STRING(lp_panic_action, &Globals.szPanicAction)
5114 FN_GLOBAL_STRING(lp_adduser_script, &Globals.szAddUserScript)
5115 FN_GLOBAL_STRING(lp_renameuser_script, &Globals.szRenameUserScript)
5116 FN_GLOBAL_STRING(lp_deluser_script, &Globals.szDelUserScript)
5117
5118 FN_GLOBAL_CONST_STRING(lp_guestaccount, &Globals.szGuestaccount)
5119 FN_GLOBAL_STRING(lp_addgroup_script, &Globals.szAddGroupScript)
5120 FN_GLOBAL_STRING(lp_delgroup_script, &Globals.szDelGroupScript)
5121 FN_GLOBAL_STRING(lp_addusertogroup_script, &Globals.szAddUserToGroupScript)
5122 FN_GLOBAL_STRING(lp_deluserfromgroup_script, &Globals.szDelUserFromGroupScript)
5123 FN_GLOBAL_STRING(lp_setprimarygroup_script, &Globals.szSetPrimaryGroupScript)
5124
5125 FN_GLOBAL_STRING(lp_addmachine_script, &Globals.szAddMachineScript)
5126
5127 FN_GLOBAL_STRING(lp_shutdown_script, &Globals.szShutdownScript)
5128 FN_GLOBAL_STRING(lp_abort_shutdown_script, &Globals.szAbortShutdownScript)
5129 FN_GLOBAL_STRING(lp_username_map_script, &Globals.szUsernameMapScript)
5130
5131 FN_GLOBAL_STRING(lp_check_password_script, &Globals.szCheckPasswordScript)
5132
5133 FN_GLOBAL_STRING(lp_wins_hook, &Globals.szWINSHook)
5134 FN_GLOBAL_CONST_STRING(lp_template_homedir, &Globals.szTemplateHomedir)
5135 FN_GLOBAL_CONST_STRING(lp_template_shell, &Globals.szTemplateShell)
5136 FN_GLOBAL_CONST_STRING(lp_winbind_separator, &Globals.szWinbindSeparator)
5137 FN_GLOBAL_INTEGER(lp_acl_compatibility, &Globals.iAclCompat)
5138 FN_GLOBAL_BOOL(lp_winbind_enum_users, &Globals.bWinbindEnumUsers)
5139 FN_GLOBAL_BOOL(lp_winbind_enum_groups, &Globals.bWinbindEnumGroups)
5140 FN_GLOBAL_BOOL(lp_winbind_use_default_domain, &Globals.bWinbindUseDefaultDomain)
5141 FN_GLOBAL_BOOL(lp_winbind_trusted_domains_only, &Globals.bWinbindTrustedDomainsOnly)
5142 FN_GLOBAL_BOOL(lp_winbind_nested_groups, &Globals.bWinbindNestedGroups)
5143 FN_GLOBAL_INTEGER(lp_winbind_expand_groups, &Globals.winbind_expand_groups)
5144 FN_GLOBAL_BOOL(lp_winbind_refresh_tickets, &Globals.bWinbindRefreshTickets)
5145 FN_GLOBAL_BOOL(lp_winbind_offline_logon, &Globals.bWinbindOfflineLogon)
5146 FN_GLOBAL_BOOL(lp_winbind_normalize_names, &Globals.bWinbindNormalizeNames)
5147 FN_GLOBAL_BOOL(lp_winbind_rpc_only, &Globals.bWinbindRpcOnly)
5148
5149 FN_GLOBAL_CONST_STRING(lp_idmap_backend, &Globals.szIdmapBackend)
5150 FN_GLOBAL_STRING(lp_idmap_alloc_backend, &Globals.szIdmapAllocBackend)
5151 FN_GLOBAL_INTEGER(lp_idmap_cache_time, &Globals.iIdmapCacheTime)
5152 FN_GLOBAL_INTEGER(lp_idmap_negative_cache_time, &Globals.iIdmapNegativeCacheTime)
5153 FN_GLOBAL_INTEGER(lp_keepalive, &Globals.iKeepalive)
5154 FN_GLOBAL_BOOL(lp_passdb_expand_explicit, &Globals.bPassdbExpandExplicit)
5155
5156 FN_GLOBAL_STRING(lp_ldap_suffix, &Globals.szLdapSuffix)
5157 FN_GLOBAL_STRING(lp_ldap_admin_dn, &Globals.szLdapAdminDn)
5158 FN_GLOBAL_INTEGER(lp_ldap_ssl, &Globals.ldap_ssl)
5159 FN_GLOBAL_INTEGER(lp_ldap_passwd_sync, &Globals.ldap_passwd_sync)
5160 FN_GLOBAL_BOOL(lp_ldap_delete_dn, &Globals.ldap_delete_dn)
5161 FN_GLOBAL_INTEGER(lp_ldap_replication_sleep, &Globals.ldap_replication_sleep)
5162 FN_GLOBAL_INTEGER(lp_ldap_timeout, &Globals.ldap_timeout)
5163 FN_GLOBAL_INTEGER(lp_ldap_connection_timeout, &Globals.ldap_connection_timeout)
5164 FN_GLOBAL_INTEGER(lp_ldap_page_size, &Globals.ldap_page_size)
5165 FN_GLOBAL_INTEGER(lp_ldap_debug_level, &Globals.ldap_debug_level)
5166 FN_GLOBAL_INTEGER(lp_ldap_debug_threshold, &Globals.ldap_debug_threshold)
5167 FN_GLOBAL_STRING(lp_add_share_cmd, &Globals.szAddShareCommand)
5168 FN_GLOBAL_STRING(lp_change_share_cmd, &Globals.szChangeShareCommand)
5169 FN_GLOBAL_STRING(lp_delete_share_cmd, &Globals.szDeleteShareCommand)
5170 FN_GLOBAL_STRING(lp_usershare_path, &Globals.szUsersharePath)
5171 FN_GLOBAL_LIST(lp_usershare_prefix_allow_list, &Globals.szUsersharePrefixAllowList)
5172 FN_GLOBAL_LIST(lp_usershare_prefix_deny_list, &Globals.szUsersharePrefixDenyList)
5173
5174 FN_GLOBAL_LIST(lp_eventlog_list, &Globals.szEventLogs)
5175
5176 FN_GLOBAL_BOOL(lp_registry_shares, &Globals.bRegistryShares)
5177 FN_GLOBAL_BOOL(lp_usershare_allow_guests, &Globals.bUsershareAllowGuests)
5178 FN_GLOBAL_BOOL(lp_usershare_owner_only, &Globals.bUsershareOwnerOnly)
5179 FN_GLOBAL_BOOL(lp_disable_netbios, &Globals.bDisableNetbios)
5180 FN_GLOBAL_BOOL(lp_reset_on_zero_vc, &Globals.bResetOnZeroVC)
5181 FN_GLOBAL_BOOL(lp_ms_add_printer_wizard, &Globals.bMsAddPrinterWizard)
5182 FN_GLOBAL_BOOL(lp_dns_proxy, &Globals.bDNSproxy)
5183 FN_GLOBAL_BOOL(lp_wins_support, &Globals.bWINSsupport)
5184 FN_GLOBAL_BOOL(lp_we_are_a_wins_server, &Globals.bWINSsupport)
5185 FN_GLOBAL_BOOL(lp_wins_proxy, &Globals.bWINSproxy)
5186 FN_GLOBAL_BOOL(lp_local_master, &Globals.bLocalMaster)
5187 FN_GLOBAL_BOOL(lp_domain_logons, &Globals.bDomainLogons)
5188 FN_GLOBAL_LIST(lp_init_logon_delayed_hosts, &Globals.szInitLogonDelayedHosts)
5189 FN_GLOBAL_INTEGER(lp_init_logon_delay, &Globals.InitLogonDelay)
5190 FN_GLOBAL_BOOL(lp_load_printers, &Globals.bLoadPrinters)
5191 FN_GLOBAL_BOOL(lp_readraw, &Globals.bReadRaw)
5192 FN_GLOBAL_BOOL(lp_large_readwrite, &Globals.bLargeReadwrite)
5193 FN_GLOBAL_BOOL(lp_writeraw, &Globals.bWriteRaw)
5194 FN_GLOBAL_BOOL(lp_null_passwords, &Globals.bNullPasswords)
5195 FN_GLOBAL_BOOL(lp_obey_pam_restrictions, &Globals.bObeyPamRestrictions)
5196 FN_GLOBAL_BOOL(lp_encrypted_passwords, &Globals.bEncryptPasswords)
5197 FN_GLOBAL_BOOL(lp_update_encrypted, &Globals.bUpdateEncrypt)
5198 FN_GLOBAL_INTEGER(lp_client_schannel, &Globals.clientSchannel)
5199 FN_GLOBAL_INTEGER(lp_server_schannel, &Globals.serverSchannel)
5200 FN_GLOBAL_BOOL(lp_syslog_only, &Globals.bSyslogOnly)
5201 FN_GLOBAL_BOOL(lp_timestamp_logs, &Globals.bTimestampLogs)
5202 FN_GLOBAL_BOOL(lp_debug_prefix_timestamp, &Globals.bDebugPrefixTimestamp)
5203 FN_GLOBAL_BOOL(lp_debug_hires_timestamp, &Globals.bDebugHiresTimestamp)
5204 FN_GLOBAL_BOOL(lp_debug_pid, &Globals.bDebugPid)
5205 FN_GLOBAL_BOOL(lp_debug_uid, &Globals.bDebugUid)
5206 FN_GLOBAL_BOOL(lp_debug_class, &Globals.bDebugClass)
5207 FN_GLOBAL_BOOL(lp_enable_core_files, &Globals.bEnableCoreFiles)
5208 FN_GLOBAL_BOOL(lp_browse_list, &Globals.bBrowseList)
5209 FN_GLOBAL_BOOL(lp_nis_home_map, &Globals.bNISHomeMap)
5210 static FN_GLOBAL_BOOL(lp_time_server, &Globals.bTimeServer)
5211 FN_GLOBAL_BOOL(lp_bind_interfaces_only, &Globals.bBindInterfacesOnly)
5212 FN_GLOBAL_BOOL(lp_pam_password_change, &Globals.bPamPasswordChange)
5213 FN_GLOBAL_BOOL(lp_unix_password_sync, &Globals.bUnixPasswdSync)
5214 FN_GLOBAL_BOOL(lp_passwd_chat_debug, &Globals.bPasswdChatDebug)
5215 FN_GLOBAL_INTEGER(lp_passwd_chat_timeout, &Globals.iPasswdChatTimeout)
5216 FN_GLOBAL_BOOL(lp_nt_pipe_support, &Globals.bNTPipeSupport)
5217 FN_GLOBAL_BOOL(lp_nt_status_support, &Globals.bNTStatusSupport)
5218 FN_GLOBAL_BOOL(lp_stat_cache, &Globals.bStatCache)
5219 FN_GLOBAL_INTEGER(lp_max_stat_cache_size, &Globals.iMaxStatCacheSize)
5220 FN_GLOBAL_BOOL(lp_allow_trusted_domains, &Globals.bAllowTrustedDomains)
5221 FN_GLOBAL_INTEGER(lp_restrict_anonymous, &Globals.restrict_anonymous)
5222 FN_GLOBAL_BOOL(lp_lanman_auth, &Globals.bLanmanAuth)
5223 FN_GLOBAL_BOOL(lp_ntlm_auth, &Globals.bNTLMAuth)
5224 FN_GLOBAL_BOOL(lp_client_plaintext_auth, &Globals.bClientPlaintextAuth)
5225 FN_GLOBAL_BOOL(lp_client_lanman_auth, &Globals.bClientLanManAuth)
5226 FN_GLOBAL_BOOL(lp_client_ntlmv2_auth, &Globals.bClientNTLMv2Auth)
5227 FN_GLOBAL_BOOL(lp_host_msdfs, &Globals.bHostMSDfs)
5228 FN_GLOBAL_BOOL(lp_kernel_oplocks, &Globals.bKernelOplocks)
5229 FN_GLOBAL_BOOL(lp_enhanced_browsing, &Globals.enhanced_browsing)
5230 FN_GLOBAL_BOOL(lp_use_mmap, &Globals.bUseMmap)
5231 FN_GLOBAL_BOOL(lp_unix_extensions, &Globals.bUnixExtensions)
5232 FN_GLOBAL_BOOL(lp_use_spnego, &Globals.bUseSpnego)
5233 FN_GLOBAL_BOOL(lp_client_use_spnego, &Globals.bClientUseSpnego)
5234 FN_GLOBAL_BOOL(lp_hostname_lookups, &Globals.bHostnameLookups)
5235 FN_LOCAL_PARM_BOOL(lp_change_notify, bChangeNotify)
5236 FN_LOCAL_PARM_BOOL(lp_kernel_change_notify, bKernelChangeNotify)
5237 FN_GLOBAL_BOOL(lp_use_kerberos_keytab, &Globals.bUseKerberosKeytab)
5238 FN_GLOBAL_BOOL(lp_defer_sharing_violations, &Globals.bDeferSharingViolations)
5239 FN_GLOBAL_BOOL(lp_enable_privileges, &Globals.bEnablePrivileges)
5240 FN_GLOBAL_BOOL(lp_enable_asu_support, &Globals.bASUSupport)
5241 FN_GLOBAL_INTEGER(lp_os_level, &Globals.os_level)
5242 FN_GLOBAL_INTEGER(lp_max_ttl, &Globals.max_ttl)
5243 FN_GLOBAL_INTEGER(lp_max_wins_ttl, &Globals.max_wins_ttl)
5244 FN_GLOBAL_INTEGER(lp_min_wins_ttl, &Globals.min_wins_ttl)
5245 FN_GLOBAL_INTEGER(lp_max_log_size, &Globals.max_log_size)
5246 FN_GLOBAL_INTEGER(lp_max_open_files, &Globals.max_open_files)
5247 FN_GLOBAL_INTEGER(lp_open_files_db_hash_size, &Globals.open_files_db_hash_size)
5248 FN_GLOBAL_INTEGER(lp_maxxmit, &Globals.max_xmit)
5249 FN_GLOBAL_INTEGER(lp_maxmux, &Globals.max_mux)
5250 FN_GLOBAL_INTEGER(lp_passwordlevel, &Globals.pwordlevel)
5251 FN_GLOBAL_INTEGER(lp_usernamelevel, &Globals.unamelevel)
5252 FN_GLOBAL_INTEGER(lp_deadtime, &Globals.deadtime)
5253 FN_GLOBAL_BOOL(lp_getwd_cache, &Globals.getwd_cache)
5254 FN_GLOBAL_INTEGER(lp_maxprotocol, &Globals.maxprotocol)
5255 FN_GLOBAL_INTEGER(lp_minprotocol, &Globals.minprotocol)
5256 FN_GLOBAL_INTEGER(lp_security, &Globals.security)
5257 FN_GLOBAL_LIST(lp_auth_methods, &Globals.AuthMethods)
5258 FN_GLOBAL_BOOL(lp_paranoid_server_security, &Globals.paranoid_server_security)
5259 FN_GLOBAL_INTEGER(lp_maxdisksize, &Globals.maxdisksize)
5260 FN_GLOBAL_INTEGER(lp_lpqcachetime, &Globals.lpqcachetime)
5261 FN_GLOBAL_INTEGER(lp_max_smbd_processes, &Globals.iMaxSmbdProcesses)
5262 FN_GLOBAL_BOOL(_lp_disable_spoolss, &Globals.bDisableSpoolss)
5263 FN_GLOBAL_INTEGER(lp_syslog, &Globals.syslog)
5264 static FN_GLOBAL_INTEGER(lp_announce_as, &Globals.announce_as)
5265 FN_GLOBAL_INTEGER(lp_lm_announce, &Globals.lm_announce)
5266 FN_GLOBAL_INTEGER(lp_lm_interval, &Globals.lm_interval)
5267 FN_GLOBAL_INTEGER(lp_machine_password_timeout, &Globals.machine_password_timeout)
5268 FN_GLOBAL_INTEGER(lp_map_to_guest, &Globals.map_to_guest)
5269 FN_GLOBAL_INTEGER(lp_oplock_break_wait_time, &Globals.oplock_break_wait_time)
5270 FN_GLOBAL_INTEGER(lp_lock_spin_time, &Globals.iLockSpinTime)
5271 FN_GLOBAL_INTEGER(lp_usershare_max_shares, &Globals.iUsershareMaxShares)
5272 FN_GLOBAL_CONST_STRING(lp_socket_options, &Globals.szSocketOptions)
5273 FN_GLOBAL_INTEGER(lp_config_backend, &Globals.ConfigBackend)
5274
5275 FN_LOCAL_STRING(lp_preexec, szPreExec)
5276 FN_LOCAL_STRING(lp_postexec, szPostExec)
5277 FN_LOCAL_STRING(lp_rootpreexec, szRootPreExec)
5278 FN_LOCAL_STRING(lp_rootpostexec, szRootPostExec)
5279 FN_LOCAL_STRING(lp_servicename, szService)
5280 FN_LOCAL_CONST_STRING(lp_const_servicename, szService)
5281 FN_LOCAL_STRING(lp_pathname, szPath)
5282 FN_LOCAL_STRING(lp_dontdescend, szDontdescend)
5283 FN_LOCAL_STRING(lp_username, szUsername)
5284 FN_LOCAL_LIST(lp_invalid_users, szInvalidUsers)
5285 FN_LOCAL_LIST(lp_valid_users, szValidUsers)
5286 FN_LOCAL_LIST(lp_admin_users, szAdminUsers)
5287 FN_GLOBAL_LIST(lp_svcctl_list, &Globals.szServicesList)
5288 FN_LOCAL_STRING(lp_cups_options, szCupsOptions)
5289 FN_GLOBAL_STRING(lp_cups_server, &Globals.szCupsServer)
5290 FN_GLOBAL_STRING(lp_iprint_server, &Globals.szIPrintServer)
5291 FN_GLOBAL_INTEGER(lp_cups_connection_timeout, &Globals.cups_connection_timeout)
5292 FN_GLOBAL_CONST_STRING(lp_ctdbd_socket, &Globals.ctdbdSocket)
5293 FN_GLOBAL_LIST(lp_cluster_addresses, &Globals.szClusterAddresses)
5294 FN_GLOBAL_BOOL(lp_clustering, &Globals.clustering)
5295 FN_LOCAL_STRING(lp_printcommand, szPrintcommand)
5296 FN_LOCAL_STRING(lp_lpqcommand, szLpqcommand)
5297 FN_LOCAL_STRING(lp_lprmcommand, szLprmcommand)
5298 FN_LOCAL_STRING(lp_lppausecommand, szLppausecommand)
5299 FN_LOCAL_STRING(lp_lpresumecommand, szLpresumecommand)
5300 FN_LOCAL_STRING(lp_queuepausecommand, szQueuepausecommand)
5301 FN_LOCAL_STRING(lp_queueresumecommand, szQueueresumecommand)
5302 static FN_LOCAL_STRING(_lp_printername, szPrintername)
5303 FN_LOCAL_CONST_STRING(lp_printjob_username, szPrintjobUsername)
5304 FN_LOCAL_LIST(lp_hostsallow, szHostsallow)
5305 FN_LOCAL_LIST(lp_hostsdeny, szHostsdeny)
5306 FN_LOCAL_STRING(lp_magicscript, szMagicScript)
5307 FN_LOCAL_STRING(lp_magicoutput, szMagicOutput)
5308 FN_LOCAL_STRING(lp_comment, comment)
5309 FN_LOCAL_STRING(lp_force_user, force_user)
5310 FN_LOCAL_STRING(lp_force_group, force_group)
5311 FN_LOCAL_LIST(lp_readlist, readlist)
5312 FN_LOCAL_LIST(lp_writelist, writelist)
5313 FN_LOCAL_LIST(lp_printer_admin, printer_admin)
5314 FN_LOCAL_STRING(lp_fstype, fstype)
5315 FN_LOCAL_LIST(lp_vfs_objects, szVfsObjects)
5316 FN_LOCAL_STRING(lp_msdfs_proxy, szMSDfsProxy)
5317 static FN_LOCAL_STRING(lp_volume, volume)
5318 FN_LOCAL_STRING(lp_veto_files, szVetoFiles)
5319 FN_LOCAL_STRING(lp_hide_files, szHideFiles)
5320 FN_LOCAL_STRING(lp_veto_oplocks, szVetoOplockFiles)
5321 FN_LOCAL_BOOL(lp_msdfs_root, bMSDfsRoot)
5322 FN_LOCAL_STRING(lp_aio_write_behind, szAioWriteBehind)
5323 FN_LOCAL_STRING(lp_dfree_command, szDfree)
5324 FN_LOCAL_BOOL(lp_autoloaded, autoloaded)
5325 FN_LOCAL_BOOL(lp_preexec_close, bPreexecClose)
5326 FN_LOCAL_BOOL(lp_rootpreexec_close, bRootpreexecClose)
5327 FN_LOCAL_INTEGER(lp_casesensitive, iCaseSensitive)
5328 FN_LOCAL_BOOL(lp_preservecase, bCasePreserve)
5329 FN_LOCAL_BOOL(lp_shortpreservecase, bShortCasePreserve)
5330 FN_LOCAL_BOOL(lp_hide_dot_files, bHideDotFiles)
5331 FN_LOCAL_BOOL(lp_hide_special_files, bHideSpecialFiles)
5332 FN_LOCAL_BOOL(lp_hideunreadable, bHideUnReadable)
5333 FN_LOCAL_BOOL(lp_hideunwriteable_files, bHideUnWriteableFiles)
5334 FN_LOCAL_BOOL(lp_browseable, bBrowseable)
5335 FN_LOCAL_BOOL(lp_readonly, bRead_only)
5336 FN_LOCAL_BOOL(lp_no_set_dir, bNo_set_dir)
5337 FN_LOCAL_BOOL(lp_guest_ok, bGuest_ok)
5338 FN_LOCAL_BOOL(lp_guest_only, bGuest_only)
5339 FN_LOCAL_BOOL(lp_administrative_share, bAdministrative_share)
5340 FN_LOCAL_BOOL(lp_print_ok, bPrint_ok)
5341 FN_LOCAL_BOOL(lp_map_hidden, bMap_hidden)
5342 FN_LOCAL_BOOL(lp_map_archive, bMap_archive)
5343 FN_LOCAL_BOOL(lp_store_dos_attributes, bStoreDosAttributes)
5344 FN_LOCAL_BOOL(lp_dmapi_support, bDmapiSupport)
5345 FN_LOCAL_PARM_BOOL(lp_locking, bLocking)
5346 FN_LOCAL_PARM_INTEGER(lp_strict_locking, iStrictLocking)
5347 FN_LOCAL_PARM_BOOL(lp_posix_locking, bPosixLocking)
5348 FN_LOCAL_BOOL(lp_share_modes, bShareModes)
5349 FN_LOCAL_BOOL(lp_oplocks, bOpLocks)
5350 FN_LOCAL_BOOL(lp_level2_oplocks, bLevel2OpLocks)
5351 FN_LOCAL_BOOL(lp_onlyuser, bOnlyUser)
5352 FN_LOCAL_PARM_BOOL(lp_manglednames, bMangledNames)
5353 FN_LOCAL_BOOL(lp_widelinks, bWidelinks)
5354 FN_LOCAL_BOOL(lp_symlinks, bSymlinks)
5355 FN_LOCAL_BOOL(lp_syncalways, bSyncAlways)
5356 FN_LOCAL_BOOL(lp_strict_allocate, bStrictAllocate)
5357 FN_LOCAL_BOOL(lp_strict_sync, bStrictSync)
5358 FN_LOCAL_BOOL(lp_map_system, bMap_system)
5359 FN_LOCAL_BOOL(lp_delete_readonly, bDeleteReadonly)
5360 FN_LOCAL_BOOL(lp_fake_oplocks, bFakeOplocks)
5361 FN_LOCAL_BOOL(lp_recursive_veto_delete, bDeleteVetoFiles)
5362 FN_LOCAL_BOOL(lp_dos_filemode, bDosFilemode)
5363 FN_LOCAL_BOOL(lp_dos_filetimes, bDosFiletimes)
5364 FN_LOCAL_BOOL(lp_dos_filetime_resolution, bDosFiletimeResolution)
5365 FN_LOCAL_BOOL(lp_fake_dir_create_times, bFakeDirCreateTimes)
5366 FN_LOCAL_BOOL(lp_blocking_locks, bBlockingLocks)
5367 FN_LOCAL_BOOL(lp_inherit_perms, bInheritPerms)
5368 FN_LOCAL_BOOL(lp_inherit_acls, bInheritACLS)
5369 FN_LOCAL_BOOL(lp_inherit_owner, bInheritOwner)
5370 FN_LOCAL_BOOL(lp_use_client_driver, bUseClientDriver)
5371 FN_LOCAL_BOOL(lp_default_devmode, bDefaultDevmode)
5372 FN_LOCAL_BOOL(lp_force_printername, bForcePrintername)
5373 FN_LOCAL_BOOL(lp_nt_acl_support, bNTAclSupport)
5374 FN_LOCAL_BOOL(lp_force_unknown_acl_user, bForceUnknownAclUser)
5375 FN_LOCAL_BOOL(lp_ea_support, bEASupport)
5376 FN_LOCAL_BOOL(_lp_use_sendfile, bUseSendfile)
5377 FN_LOCAL_BOOL(lp_profile_acls, bProfileAcls)
5378 FN_LOCAL_BOOL(lp_map_acl_inherit, bMap_acl_inherit)
5379 FN_LOCAL_BOOL(lp_afs_share, bAfs_Share)
5380 FN_LOCAL_BOOL(lp_acl_check_permissions, bAclCheckPermissions)
5381 FN_LOCAL_BOOL(lp_acl_group_control, bAclGroupControl)
5382 FN_LOCAL_BOOL(lp_acl_map_full_control, bAclMapFullControl)
5383 FN_LOCAL_INTEGER(lp_create_mask, iCreate_mask)
5384 FN_LOCAL_INTEGER(lp_force_create_mode, iCreate_force_mode)
5385 FN_LOCAL_INTEGER(lp_security_mask, iSecurity_mask)
5386 FN_LOCAL_INTEGER(lp_force_security_mode, iSecurity_force_mode)
5387 FN_LOCAL_INTEGER(lp_dir_mask, iDir_mask)
5388 FN_LOCAL_INTEGER(lp_force_dir_mode, iDir_force_mode)
5389 FN_LOCAL_INTEGER(lp_dir_security_mask, iDir_Security_mask)
5390 FN_LOCAL_INTEGER(lp_force_dir_security_mode, iDir_Security_force_mode)
5391 FN_LOCAL_INTEGER(lp_max_connections, iMaxConnections)
5392 FN_LOCAL_INTEGER(lp_defaultcase, iDefaultCase)
5393 FN_LOCAL_INTEGER(lp_minprintspace, iMinPrintSpace)
5394 FN_LOCAL_INTEGER(lp_printing, iPrinting)
5395 FN_LOCAL_INTEGER(lp_max_reported_jobs, iMaxReportedPrintJobs)
5396 FN_LOCAL_INTEGER(lp_oplock_contention_limit, iOplockContentionLimit)
5397 FN_LOCAL_INTEGER(lp_csc_policy, iCSCPolicy)
5398 FN_LOCAL_INTEGER(lp_write_cache_size, iWriteCacheSize)
5399 FN_LOCAL_INTEGER(lp_block_size, iBlock_size)
5400 FN_LOCAL_INTEGER(lp_dfree_cache_time, iDfreeCacheTime)
5401 FN_LOCAL_INTEGER(lp_allocation_roundup_size, iallocation_roundup_size)
5402 FN_LOCAL_INTEGER(lp_aio_read_size, iAioReadSize)
5403 FN_LOCAL_INTEGER(lp_aio_write_size, iAioWriteSize)
5404 FN_LOCAL_INTEGER(lp_map_readonly, iMap_readonly)
5405 FN_LOCAL_INTEGER(lp_directory_name_cache_size, iDirectoryNameCacheSize)
5406 FN_LOCAL_INTEGER(lp_smb_encrypt, ismb_encrypt)
5407 FN_LOCAL_CHAR(lp_magicchar, magic_char)
5408 FN_GLOBAL_INTEGER(lp_winbind_cache_time, &Globals.winbind_cache_time)
5409 FN_GLOBAL_INTEGER(lp_winbind_reconnect_delay, &Globals.winbind_reconnect_delay)
5410 FN_GLOBAL_LIST(lp_winbind_nss_info, &Globals.szWinbindNssInfo)
5411 FN_GLOBAL_INTEGER(lp_algorithmic_rid_base, &Globals.AlgorithmicRidBase)
5412 FN_GLOBAL_INTEGER(lp_name_cache_timeout, &Globals.name_cache_timeout)
5413 FN_GLOBAL_INTEGER(lp_client_signing, &Globals.client_signing)
5414 FN_GLOBAL_INTEGER(lp_server_signing, &Globals.server_signing)
5415 FN_GLOBAL_INTEGER(lp_client_ldap_sasl_wrapping, &Globals.client_ldap_sasl_wrapping)
5416
5417 /* local prototypes */
5418
5419 static int map_parameter(const char *pszParmName);
5420 static int map_parameter_canonical(const char *pszParmName, bool *inverse);
5421 static bool set_boolean(bool *pb, const char *pszParmValue);
5422 static const char *get_boolean(bool bool_value);
5423 static int getservicebyname(const char *pszServiceName,
5424                             struct service *pserviceDest);
5425 static void copy_service(struct service *pserviceDest,
5426                          struct service *pserviceSource,
5427                          struct bitmap *pcopymapDest);
5428 static bool do_parameter(const char *pszParmName, const char *pszParmValue,
5429                          void *userdata);
5430 static bool do_section(const char *pszSectionName, void *userdata);
5431 static void init_copymap(struct service *pservice);
5432 static bool hash_a_service(const char *name, int number);
5433 static void free_service_byindex(int iService);
5434 static void free_param_opts(struct param_opt_struct **popts);
5435 static char * canonicalize_servicename(const char *name);
5436 static void show_parameter(int parmIndex);
5437 static bool is_synonym_of(int parm1, int parm2, bool *inverse);
5438
5439 /*
5440  * This is a helper function for parametrical options support.  It returns a
5441  * pointer to parametrical option value if it exists or NULL otherwise. Actual
5442  * parametrical functions are quite simple
5443  */
5444 static struct param_opt_struct *get_parametrics(int snum, const char *type,
5445                                                 const char *option)
5446 {
5447         bool global_section = False;
5448         char* param_key;
5449         struct param_opt_struct *data;
5450         
5451         if (snum >= iNumServices) return NULL;
5452         
5453         if (snum < 0) { 
5454                 data = Globals.param_opt;
5455                 global_section = True;
5456         } else {
5457                 data = ServicePtrs[snum]->param_opt;
5458         }
5459     
5460         if (asprintf(&param_key, "%s:%s", type, option) == -1) {
5461                 DEBUG(0,("asprintf failed!\n"));
5462                 return NULL;
5463         }
5464
5465         while (data) {
5466                 if (strwicmp(data->key, param_key) == 0) {
5467                         string_free(&param_key);
5468                         return data;
5469                 }
5470                 data = data->next;
5471         }
5472
5473         if (!global_section) {
5474                 /* Try to fetch the same option but from globals */
5475                 /* but only if we are not already working with Globals */
5476                 data = Globals.param_opt;
5477                 while (data) {
5478                         if (strwicmp(data->key, param_key) == 0) {
5479                                 string_free(&param_key);
5480                                 return data;
5481                         }
5482                         data = data->next;
5483                 }
5484         }
5485
5486         string_free(&param_key);
5487         
5488         return NULL;
5489 }
5490
5491
5492 #define MISSING_PARAMETER(name) \
5493     DEBUG(0, ("%s(): value is NULL or empty!\n", #name))
5494
5495 /*******************************************************************
5496 convenience routine to return int parameters.
5497 ********************************************************************/
5498 static int lp_int(const char *s)
5499 {
5500
5501         if (!s || !*s) {
5502                 MISSING_PARAMETER(lp_int);
5503                 return (-1);
5504         }
5505
5506         return (int)strtol(s, NULL, 0);
5507 }
5508
5509 /*******************************************************************
5510 convenience routine to return unsigned long parameters.
5511 ********************************************************************/
5512 static unsigned long lp_ulong(const char *s)
5513 {
5514
5515         if (!s || !*s) {
5516                 MISSING_PARAMETER(lp_ulong);
5517                 return (0);
5518         }
5519
5520         return strtoul(s, NULL, 0);
5521 }
5522
5523 /*******************************************************************
5524 convenience routine to return boolean parameters.
5525 ********************************************************************/
5526 static bool lp_bool(const char *s)
5527 {
5528         bool ret = False;
5529
5530         if (!s || !*s) {
5531                 MISSING_PARAMETER(lp_bool);
5532                 return False;
5533         }
5534         
5535         if (!set_boolean(&ret,s)) {
5536                 DEBUG(0,("lp_bool(%s): value is not boolean!\n",s));
5537                 return False;
5538         }
5539
5540         return ret;
5541 }
5542
5543 /*******************************************************************
5544 convenience routine to return enum parameters.
5545 ********************************************************************/
5546 static int lp_enum(const char *s,const struct enum_list *_enum)
5547 {
5548         int i;
5549
5550         if (!s || !*s || !_enum) {
5551                 MISSING_PARAMETER(lp_enum);
5552                 return (-1);
5553         }
5554         
5555         for (i=0; _enum[i].name; i++) {
5556                 if (strequal(_enum[i].name,s))
5557                         return _enum[i].value;
5558         }
5559
5560         DEBUG(0,("lp_enum(%s,enum): value is not in enum_list!\n",s));
5561         return (-1);
5562 }
5563
5564 #undef MISSING_PARAMETER
5565
5566 /* DO NOT USE lp_parm_string ANYMORE!!!!
5567  * use lp_parm_const_string or lp_parm_talloc_string
5568  *
5569  * lp_parm_string is only used to let old modules find this symbol
5570  */
5571 #undef lp_parm_string
5572  char *lp_parm_string(const char *servicename, const char *type, const char *option);
5573  char *lp_parm_string(const char *servicename, const char *type, const char *option)
5574 {
5575         return lp_parm_talloc_string(lp_servicenumber(servicename), type, option, NULL);
5576 }
5577
5578 /* Return parametric option from a given service. Type is a part of option before ':' */
5579 /* Parametric option has following syntax: 'Type: option = value' */
5580 /* the returned value is talloced on the talloc_tos() */
5581 char *lp_parm_talloc_string(int snum, const char *type, const char *option, const char *def)
5582 {
5583         struct param_opt_struct *data = get_parametrics(snum, type, option);
5584         
5585         if (data == NULL||data->value==NULL) {
5586                 if (def) {
5587                         return lp_string(def);
5588                 } else {
5589                         return NULL;
5590                 }
5591         }
5592
5593         return lp_string(data->value);
5594 }
5595
5596 /* Return parametric option from a given service. Type is a part of option before ':' */
5597 /* Parametric option has following syntax: 'Type: option = value' */
5598 const char *lp_parm_const_string(int snum, const char *type, const char *option, const char *def)
5599 {
5600         struct param_opt_struct *data = get_parametrics(snum, type, option);
5601         
5602         if (data == NULL||data->value==NULL)
5603                 return def;
5604                 
5605         return data->value;
5606 }
5607
5608 /* Return parametric option from a given service. Type is a part of option before ':' */
5609 /* Parametric option has following syntax: 'Type: option = value' */
5610
5611 const char **lp_parm_string_list(int snum, const char *type, const char *option, const char **def)
5612 {
5613         struct param_opt_struct *data = get_parametrics(snum, type, option);
5614
5615         if (data == NULL||data->value==NULL)
5616                 return (const char **)def;
5617                 
5618         if (data->list==NULL) {
5619                 data->list = str_list_make(NULL, data->value, NULL);
5620         }
5621
5622         return (const char **)data->list;
5623 }
5624
5625 /* Return parametric option from a given service. Type is a part of option before ':' */
5626 /* Parametric option has following syntax: 'Type: option = value' */
5627
5628 int lp_parm_int(int snum, const char *type, const char *option, int def)
5629 {
5630         struct param_opt_struct *data = get_parametrics(snum, type, option);
5631         
5632         if (data && data->value && *data->value)
5633                 return lp_int(data->value);
5634
5635         return def;
5636 }
5637
5638 /* Return parametric option from a given service. Type is a part of option before ':' */
5639 /* Parametric option has following syntax: 'Type: option = value' */
5640
5641 unsigned long lp_parm_ulong(int snum, const char *type, const char *option, unsigned long def)
5642 {
5643         struct param_opt_struct *data = get_parametrics(snum, type, option);
5644         
5645         if (data && data->value && *data->value)
5646                 return lp_ulong(data->value);
5647
5648         return def;
5649 }
5650
5651 /* Return parametric option from a given service. Type is a part of option before ':' */
5652 /* Parametric option has following syntax: 'Type: option = value' */
5653
5654 bool lp_parm_bool(int snum, const char *type, const char *option, bool def)
5655 {
5656         struct param_opt_struct *data = get_parametrics(snum, type, option);
5657         
5658         if (data && data->value && *data->value)
5659                 return lp_bool(data->value);
5660
5661         return def;
5662 }
5663
5664 /* Return parametric option from a given service. Type is a part of option before ':' */
5665 /* Parametric option has following syntax: 'Type: option = value' */
5666
5667 int lp_parm_enum(int snum, const char *type, const char *option,
5668                  const struct enum_list *_enum, int def)
5669 {
5670         struct param_opt_struct *data = get_parametrics(snum, type, option);
5671         
5672         if (data && data->value && *data->value && _enum)
5673                 return lp_enum(data->value, _enum);
5674
5675         return def;
5676 }
5677
5678
5679 /***************************************************************************
5680  Initialise a service to the defaults.
5681 ***************************************************************************/
5682
5683 static void init_service(struct service *pservice)
5684 {
5685         memset((char *)pservice, '\0', sizeof(struct service));
5686         copy_service(pservice, &sDefault, NULL);
5687 }
5688
5689
5690 /**
5691  * free a param_opts structure.
5692  * param_opts handling should be moved to talloc;
5693  * then this whole functions reduces to a TALLOC_FREE().
5694  */
5695
5696 static void free_param_opts(struct param_opt_struct **popts)
5697 {
5698         struct param_opt_struct *opt, *next_opt;
5699
5700         if (popts == NULL) {
5701                 return;
5702         }
5703
5704         if (*popts != NULL) {
5705                 DEBUG(5, ("Freeing parametrics:\n"));
5706         }
5707         opt = *popts;
5708         while (opt != NULL) {
5709                 string_free(&opt->key);
5710                 string_free(&opt->value);
5711                 TALLOC_FREE(opt->list);
5712                 next_opt = opt->next;
5713                 SAFE_FREE(opt);
5714                 opt = next_opt;
5715         }
5716         *popts = NULL;
5717 }
5718
5719 /***************************************************************************
5720  Free the dynamically allocated parts of a service struct.
5721 ***************************************************************************/
5722
5723 static void free_service(struct service *pservice)
5724 {
5725         if (!pservice)
5726                 return;
5727
5728         if (pservice->szService)
5729                 DEBUG(5, ("free_service: Freeing service %s\n",
5730                        pservice->szService));
5731
5732         free_parameters(getservicebyname(pservice->szService, NULL));
5733
5734         string_free(&pservice->szService);
5735         bitmap_free(pservice->copymap);
5736
5737         free_param_opts(&pservice->param_opt);
5738
5739         ZERO_STRUCTP(pservice);
5740 }
5741
5742
5743 /***************************************************************************
5744  remove a service indexed in the ServicePtrs array from the ServiceHash
5745  and free the dynamically allocated parts
5746 ***************************************************************************/
5747
5748 static void free_service_byindex(int idx)
5749 {
5750         if ( !LP_SNUM_OK(idx) ) 
5751                 return;
5752
5753         ServicePtrs[idx]->valid = False;
5754         invalid_services[num_invalid_services++] = idx;
5755
5756         /* we have to cleanup the hash record */
5757
5758         if (ServicePtrs[idx]->szService) {
5759                 char *canon_name = canonicalize_servicename(
5760                         ServicePtrs[idx]->szService );
5761                 
5762                 dbwrap_delete_bystring(ServiceHash, canon_name );
5763                 TALLOC_FREE(canon_name);
5764         }
5765
5766         free_service(ServicePtrs[idx]);
5767 }
5768
5769 /***************************************************************************
5770  Add a new service to the services array initialising it with the given 
5771  service. 
5772 ***************************************************************************/
5773
5774 static int add_a_service(const struct service *pservice, const char *name)
5775 {
5776         int i;
5777         struct service tservice;
5778         int num_to_alloc = iNumServices + 1;
5779
5780         tservice = *pservice;
5781
5782         /* it might already exist */
5783         if (name) {
5784                 i = getservicebyname(name, NULL);
5785                 if (i >= 0) {
5786                         /* Clean all parametric options for service */
5787                         /* They will be added during parsing again */
5788                         free_param_opts(&ServicePtrs[i]->param_opt);
5789                         return (i);
5790                 }
5791         }
5792
5793         /* find an invalid one */
5794         i = iNumServices;
5795         if (num_invalid_services > 0) {
5796                 i = invalid_services[--num_invalid_services];
5797         }
5798
5799         /* if not, then create one */
5800         if (i == iNumServices) {
5801                 struct service **tsp;
5802                 int *tinvalid;
5803                 
5804                 tsp = SMB_REALLOC_ARRAY_KEEP_OLD_ON_ERROR(ServicePtrs, struct service *, num_to_alloc);
5805                 if (tsp == NULL) {
5806                         DEBUG(0,("add_a_service: failed to enlarge ServicePtrs!\n"));
5807                         return (-1);
5808                 }
5809                 ServicePtrs = tsp;
5810                 ServicePtrs[iNumServices] = SMB_MALLOC_P(struct service);
5811                 if (!ServicePtrs[iNumServices]) {
5812                         DEBUG(0,("add_a_service: out of memory!\n"));
5813                         return (-1);
5814                 }
5815                 iNumServices++;
5816
5817                 /* enlarge invalid_services here for now... */
5818                 tinvalid = SMB_REALLOC_ARRAY_KEEP_OLD_ON_ERROR(invalid_services, int,
5819                                              num_to_alloc);
5820                 if (tinvalid == NULL) {
5821                         DEBUG(0,("add_a_service: failed to enlarge "
5822                                  "invalid_services!\n"));
5823                         return (-1);
5824                 }
5825                 invalid_services = tinvalid;
5826         } else {
5827                 free_service_byindex(i);
5828         }
5829
5830         ServicePtrs[i]->valid = True;
5831
5832         init_service(ServicePtrs[i]);
5833         copy_service(ServicePtrs[i], &tservice, NULL);
5834         if (name)
5835                 string_set(&ServicePtrs[i]->szService, name);
5836                 
5837         DEBUG(8,("add_a_service: Creating snum = %d for %s\n", 
5838                 i, ServicePtrs[i]->szService));
5839
5840         if (!hash_a_service(ServicePtrs[i]->szService, i)) {
5841                 return (-1);
5842         }
5843                 
5844         return (i);
5845 }
5846
5847 /***************************************************************************
5848   Convert a string to uppercase and remove whitespaces.
5849 ***************************************************************************/
5850
5851 static char *canonicalize_servicename(const char *src)
5852 {
5853         char *result;
5854
5855         if ( !src ) {
5856                 DEBUG(0,("canonicalize_servicename: NULL source name!\n"));
5857                 return NULL;
5858         }
5859
5860         result = talloc_strdup(talloc_tos(), src);
5861         SMB_ASSERT(result != NULL);
5862
5863         strlower_m(result);
5864         return result;
5865 }
5866
5867 /***************************************************************************
5868   Add a name/index pair for the services array to the hash table.
5869 ***************************************************************************/
5870
5871 static bool hash_a_service(const char *name, int idx)
5872 {
5873         char *canon_name;
5874
5875         if ( !ServiceHash ) {
5876                 DEBUG(10,("hash_a_service: creating servicehash\n"));
5877                 ServiceHash = db_open_rbt(NULL);
5878                 if ( !ServiceHash ) {
5879                         DEBUG(0,("hash_a_service: open tdb servicehash failed!\n"));
5880                         return False;
5881                 }
5882         }
5883
5884         DEBUG(10,("hash_a_service: hashing index %d for service name %s\n",
5885                 idx, name));
5886
5887         canon_name = canonicalize_servicename( name );
5888
5889         dbwrap_store_bystring(ServiceHash, canon_name,
5890                               make_tdb_data((uint8 *)&idx, sizeof(idx)),
5891                               TDB_REPLACE);
5892
5893         TALLOC_FREE(canon_name);
5894
5895         return True;
5896 }
5897
5898 /***************************************************************************
5899  Add a new home service, with the specified home directory, defaults coming
5900  from service ifrom.
5901 ***************************************************************************/
5902
5903 bool lp_add_home(const char *pszHomename, int iDefaultService,
5904                  const char *user, const char *pszHomedir)
5905 {
5906         int i;
5907
5908         i = add_a_service(ServicePtrs[iDefaultService], pszHomename);
5909
5910         if (i < 0)
5911                 return (False);
5912
5913         if (!(*(ServicePtrs[iDefaultService]->szPath))
5914             || strequal(ServicePtrs[iDefaultService]->szPath, lp_pathname(GLOBAL_SECTION_SNUM))) {
5915                 string_set(&ServicePtrs[i]->szPath, pszHomedir);
5916         }
5917
5918         if (!(*(ServicePtrs[i]->comment))) {
5919                 char *comment = NULL;
5920                 if (asprintf(&comment, "Home directory of %s", user) < 0) {
5921                         return false;
5922                 }
5923                 string_set(&ServicePtrs[i]->comment, comment);
5924                 SAFE_FREE(comment);
5925         }
5926
5927         /* set the browseable flag from the global default */
5928
5929         ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
5930
5931         ServicePtrs[i]->autoloaded = True;
5932
5933         DEBUG(3, ("adding home's share [%s] for user '%s' at '%s'\n", pszHomename, 
5934                user, ServicePtrs[i]->szPath ));
5935
5936         return (True);
5937 }
5938
5939 /***************************************************************************
5940  Add a new service, based on an old one.
5941 ***************************************************************************/
5942
5943 int lp_add_service(const char *pszService, int iDefaultService)
5944 {
5945         if (iDefaultService < 0) {
5946                 return add_a_service(&sDefault, pszService);
5947         }
5948
5949         return (add_a_service(ServicePtrs[iDefaultService], pszService));
5950 }
5951
5952 /***************************************************************************
5953  Add the IPC service.
5954 ***************************************************************************/
5955
5956 static bool lp_add_ipc(const char *ipc_name, bool guest_ok)
5957 {
5958         char *comment = NULL;
5959         int i = add_a_service(&sDefault, ipc_name);
5960
5961         if (i < 0)
5962                 return (False);
5963
5964         if (asprintf(&comment, "IPC Service (%s)",
5965                                 Globals.szServerString) < 0) {
5966                 return (False);
5967         }
5968
5969         string_set(&ServicePtrs[i]->szPath, tmpdir());
5970         string_set(&ServicePtrs[i]->szUsername, "");
5971         string_set(&ServicePtrs[i]->comment, comment);
5972         string_set(&ServicePtrs[i]->fstype, "IPC");
5973         ServicePtrs[i]->iMaxConnections = 0;
5974         ServicePtrs[i]->bAvailable = True;
5975         ServicePtrs[i]->bRead_only = True;
5976         ServicePtrs[i]->bGuest_only = False;
5977         ServicePtrs[i]->bAdministrative_share = True;
5978         ServicePtrs[i]->bGuest_ok = guest_ok;
5979         ServicePtrs[i]->bPrint_ok = False;
5980         ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
5981
5982         DEBUG(3, ("adding IPC service\n"));
5983
5984         SAFE_FREE(comment);
5985         return (True);
5986 }
5987
5988 /***************************************************************************
5989  Add a new printer service, with defaults coming from service iFrom.
5990 ***************************************************************************/
5991
5992 bool lp_add_printer(const char *pszPrintername, int iDefaultService)
5993 {
5994         const char *comment = "From Printcap";
5995         int i = add_a_service(ServicePtrs[iDefaultService], pszPrintername);
5996
5997         if (i < 0)
5998                 return (False);
5999
6000         /* note that we do NOT default the availability flag to True - */
6001         /* we take it from the default service passed. This allows all */
6002         /* dynamic printers to be disabled by disabling the [printers] */
6003         /* entry (if/when the 'available' keyword is implemented!).    */
6004
6005         /* the printer name is set to the service name. */
6006         string_set(&ServicePtrs[i]->szPrintername, pszPrintername);
6007         string_set(&ServicePtrs[i]->comment, comment);
6008
6009         /* set the browseable flag from the gloabl default */
6010         ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
6011
6012         /* Printers cannot be read_only. */
6013         ServicePtrs[i]->bRead_only = False;
6014         /* No share modes on printer services. */
6015         ServicePtrs[i]->bShareModes = False;
6016         /* No oplocks on printer services. */
6017         ServicePtrs[i]->bOpLocks = False;
6018         /* Printer services must be printable. */
6019         ServicePtrs[i]->bPrint_ok = True;
6020         
6021         DEBUG(3, ("adding printer service %s\n", pszPrintername));
6022
6023         return (True);
6024 }
6025
6026
6027 /***************************************************************************
6028  Check whether the given parameter name is valid.
6029  Parametric options (names containing a colon) are considered valid.
6030 ***************************************************************************/
6031
6032 bool lp_parameter_is_valid(const char *pszParmName)
6033 {
6034         return ((map_parameter(pszParmName) != -1) ||
6035                 (strchr(pszParmName, ':') != NULL));
6036 }
6037
6038 /***************************************************************************
6039  Check whether the given name is the name of a global parameter.
6040  Returns True for strings belonging to parameters of class
6041  P_GLOBAL, False for all other strings, also for parametric options
6042  and strings not belonging to any option.
6043 ***************************************************************************/
6044
6045 bool lp_parameter_is_global(const char *pszParmName)
6046 {
6047         int num = map_parameter(pszParmName);
6048
6049         if (num >= 0) {
6050                 return (parm_table[num].p_class == P_GLOBAL);
6051         }
6052
6053         return False;
6054 }
6055
6056 /**************************************************************************
6057  Check whether the given name is the canonical name of a parameter.
6058  Returns False if it is not a valid parameter Name.
6059  For parametric options, True is returned.
6060 **************************************************************************/
6061
6062 bool lp_parameter_is_canonical(const char *parm_name)
6063 {
6064         if (!lp_parameter_is_valid(parm_name)) {
6065                 return False;
6066         }
6067
6068         return (map_parameter(parm_name) ==
6069                 map_parameter_canonical(parm_name, NULL));
6070 }
6071
6072 /**************************************************************************
6073  Determine the canonical name for a parameter.
6074  Indicate when it is an inverse (boolean) synonym instead of a
6075  "usual" synonym.
6076 **************************************************************************/
6077
6078 bool lp_canonicalize_parameter(const char *parm_name, const char **canon_parm,
6079                                bool *inverse)
6080 {
6081         int num;
6082
6083         if (!lp_parameter_is_valid(parm_name)) {
6084                 *canon_parm = NULL;
6085                 return False;
6086         }
6087
6088         num = map_parameter_canonical(parm_name, inverse);
6089         if (num < 0) {
6090                 /* parametric option */
6091                 *canon_parm = parm_name;
6092         } else {
6093                 *canon_parm = parm_table[num].label;
6094         }
6095
6096         return True;
6097
6098 }
6099
6100 /**************************************************************************
6101  Determine the canonical name for a parameter.
6102  Turn the value given into the inverse boolean expression when
6103  the synonym is an invers boolean synonym.
6104
6105  Return True if parm_name is a valid parameter name and
6106  in case it is an invers boolean synonym, if the val string could
6107  successfully be converted to the reverse bool.
6108  Return false in all other cases.
6109 **************************************************************************/
6110
6111 bool lp_canonicalize_parameter_with_value(const char *parm_name,
6112                                           const char *val,
6113                                           const char **canon_parm,
6114                                           const char **canon_val)
6115 {
6116         int num;
6117         bool inverse;
6118
6119         if (!lp_parameter_is_valid(parm_name)) {
6120                 *canon_parm = NULL;
6121                 *canon_val = NULL;
6122                 return False;
6123         }
6124
6125         num = map_parameter_canonical(parm_name, &inverse);
6126         if (num < 0) {
6127                 /* parametric option */
6128                 *canon_parm = parm_name;
6129                 *canon_val = val;
6130         } else {
6131                 *canon_parm = parm_table[num].label;
6132                 if (inverse) {
6133                         if (!lp_invert_boolean(val, canon_val)) {
6134                                 *canon_val = NULL;
6135                                 return False;
6136                         }
6137                 } else {
6138                         *canon_val = val;
6139                 }
6140         }
6141
6142         return True;
6143 }
6144
6145 /***************************************************************************
6146  Map a parameter's string representation to something we can use. 
6147  Returns False if the parameter string is not recognised, else TRUE.
6148 ***************************************************************************/
6149
6150 static int map_parameter(const char *pszParmName)
6151 {
6152         int iIndex;
6153
6154         if (*pszParmName == '-' && !strequal(pszParmName, "-valid"))
6155                 return (-1);
6156
6157         for (iIndex = 0; parm_table[iIndex].label; iIndex++)
6158                 if (strwicmp(parm_table[iIndex].label, pszParmName) == 0)
6159                         return (iIndex);
6160
6161         /* Warn only if it isn't parametric option */
6162         if (strchr(pszParmName, ':') == NULL)
6163                 DEBUG(1, ("Unknown parameter encountered: \"%s\"\n", pszParmName));
6164         /* We do return 'fail' for parametric options as well because they are
6165            stored in different storage
6166          */
6167         return (-1);
6168 }
6169
6170 /***************************************************************************
6171  Map a parameter's string representation to the index of the canonical
6172  form of the parameter (it might be a synonym).
6173  Returns -1 if the parameter string is not recognised.
6174 ***************************************************************************/
6175
6176 static int map_parameter_canonical(const char *pszParmName, bool *inverse)
6177 {
6178         int parm_num, canon_num;
6179         bool loc_inverse = False;
6180
6181         parm_num = map_parameter(pszParmName);
6182         if ((parm_num < 0) || !(parm_table[parm_num].flags & FLAG_HIDE)) {
6183                 /* invalid, parametric or no canidate for synonyms ... */
6184                 goto done;
6185         }
6186
6187         for (canon_num = 0; parm_table[canon_num].label; canon_num++) {
6188                 if (is_synonym_of(parm_num, canon_num, &loc_inverse)) {
6189                         parm_num = canon_num;
6190                         goto done;
6191                 }
6192         }
6193
6194 done:
6195         if (inverse != NULL) {
6196                 *inverse = loc_inverse;
6197         }
6198         return parm_num;
6199 }
6200
6201 /***************************************************************************
6202  return true if parameter number parm1 is a synonym of parameter
6203  number parm2 (parm2 being the principal name).
6204  set inverse to True if parm1 is P_BOOLREV and parm2 is P_BOOL,
6205  False otherwise.
6206 ***************************************************************************/
6207
6208 static bool is_synonym_of(int parm1, int parm2, bool *inverse)
6209 {
6210         if ((parm_table[parm1].ptr == parm_table[parm2].ptr) &&
6211             (parm_table[parm1].flags & FLAG_HIDE) &&
6212             !(parm_table[parm2].flags & FLAG_HIDE))
6213         {
6214                 if (inverse != NULL) {
6215                         if ((parm_table[parm1].type == P_BOOLREV) &&
6216                             (parm_table[parm2].type == P_BOOL))
6217                         {
6218                                 *inverse = True;
6219                         } else {
6220                                 *inverse = False;
6221                         }
6222                 }
6223                 return True;
6224         }
6225         return False;
6226 }
6227
6228 /***************************************************************************
6229  Show one parameter's name, type, [values,] and flags.
6230  (helper functions for show_parameter_list)
6231 ***************************************************************************/
6232
6233 static void show_parameter(int parmIndex)
6234 {
6235         int enumIndex, flagIndex;
6236         int parmIndex2;
6237         bool hadFlag;
6238         bool hadSyn;
6239         bool inverse;
6240         const char *type[] = { "P_BOOL", "P_BOOLREV", "P_CHAR", "P_INTEGER",
6241                 "P_OCTAL", "P_LIST", "P_STRING", "P_USTRING",
6242                 "P_ENUM", "P_SEP"};
6243         unsigned flags[] = { FLAG_BASIC, FLAG_SHARE, FLAG_PRINT, FLAG_GLOBAL,
6244                 FLAG_WIZARD, FLAG_ADVANCED, FLAG_DEVELOPER, FLAG_DEPRECATED,
6245                 FLAG_HIDE, FLAG_DOS_STRING};
6246         const char *flag_names[] = { "FLAG_BASIC", "FLAG_SHARE", "FLAG_PRINT",
6247                 "FLAG_GLOBAL", "FLAG_WIZARD", "FLAG_ADVANCED", "FLAG_DEVELOPER",
6248                 "FLAG_DEPRECATED", "FLAG_HIDE", "FLAG_DOS_STRING", NULL};
6249
6250         printf("%s=%s", parm_table[parmIndex].label,
6251                type[parm_table[parmIndex].type]);
6252         if (parm_table[parmIndex].type == P_ENUM) {
6253                 printf(",");
6254                 for (enumIndex=0;
6255                      parm_table[parmIndex].enum_list[enumIndex].name;
6256                      enumIndex++)
6257                 {
6258                         printf("%s%s",
6259                                enumIndex ? "|" : "",
6260                                parm_table[parmIndex].enum_list[enumIndex].name);
6261                 }
6262         }
6263         printf(",");
6264         hadFlag = False;
6265         for (flagIndex=0; flag_names[flagIndex]; flagIndex++) {
6266                 if (parm_table[parmIndex].flags & flags[flagIndex]) {
6267                         printf("%s%s",
6268                                 hadFlag ? "|" : "",
6269                                 flag_names[flagIndex]);
6270                         hadFlag = True;
6271                 }
6272         }
6273
6274         /* output synonyms */
6275         hadSyn = False;
6276         for (parmIndex2=0; parm_table[parmIndex2].label; parmIndex2++) {
6277                 if (is_synonym_of(parmIndex, parmIndex2, &inverse)) {
6278                         printf(" (%ssynonym of %s)", inverse ? "inverse " : "",
6279                                parm_table[parmIndex2].label);
6280                 } else if (is_synonym_of(parmIndex2, parmIndex, &inverse)) {
6281                         if (!hadSyn) {
6282                                 printf(" (synonyms: ");
6283                                 hadSyn = True;
6284                         } else {
6285                                 printf(", ");
6286                         }
6287                         printf("%s%s", parm_table[parmIndex2].label,
6288                                inverse ? "[i]" : "");
6289                 }
6290         }
6291         if (hadSyn) {
6292                 printf(")");
6293         }
6294
6295         printf("\n");
6296 }
6297
6298 /***************************************************************************
6299  Show all parameter's name, type, [values,] and flags.
6300 ***************************************************************************/
6301
6302 void show_parameter_list(void)
6303 {
6304         int classIndex, parmIndex;
6305         const char *section_names[] = { "local", "global", NULL};
6306
6307         for (classIndex=0; section_names[classIndex]; classIndex++) {
6308                 printf("[%s]\n", section_names[classIndex]);
6309                 for (parmIndex = 0; parm_table[parmIndex].label; parmIndex++) {
6310                         if (parm_table[parmIndex].p_class == classIndex) {
6311                                 show_parameter(parmIndex);
6312                         }
6313                 }
6314         }
6315 }
6316
6317 /***************************************************************************
6318  Set a boolean variable from the text value stored in the passed string.
6319  Returns True in success, False if the passed string does not correctly 
6320  represent a boolean.
6321 ***************************************************************************/
6322
6323 static bool set_boolean(bool *pb, const char *pszParmValue)
6324 {
6325         bool bRetval;
6326         bool value;
6327
6328         bRetval = True;
6329         value = False;
6330         if (strwicmp(pszParmValue, "yes") == 0 ||
6331             strwicmp(pszParmValue, "true") == 0 ||
6332             strwicmp(pszParmValue, "1") == 0)
6333                 value = True;
6334         else if (strwicmp(pszParmValue, "no") == 0 ||
6335                     strwicmp(pszParmValue, "False") == 0 ||
6336                     strwicmp(pszParmValue, "0") == 0)
6337                 value = False;
6338         else {
6339                 DEBUG(2,
6340                       ("ERROR: Badly formed boolean in configuration file: \"%s\".\n",
6341                        pszParmValue));
6342                 bRetval = False;
6343         }
6344
6345         if ((pb != NULL) && (bRetval != False)) {
6346                 *pb = value;
6347         }
6348
6349         return (bRetval);
6350 }
6351
6352
6353 /***************************************************************************
6354  Check if a given string correctly represents a boolean value.
6355 ***************************************************************************/
6356
6357 bool lp_string_is_valid_boolean(const char *parm_value)
6358 {
6359         return set_boolean(NULL, parm_value);
6360 }
6361
6362 /***************************************************************************
6363  Get the standard string representation of a boolean value ("yes" or "no")
6364 ***************************************************************************/
6365
6366 static const char *get_boolean(bool bool_value)
6367 {
6368         static const char *yes_str = "yes";
6369         static const char *no_str = "no";
6370
6371         return (bool_value ? yes_str : no_str);
6372 }
6373
6374 /***************************************************************************
6375  Provide the string of the negated boolean value associated to the boolean
6376  given as a string. Returns False if the passed string does not correctly
6377  represent a boolean.
6378 ***************************************************************************/
6379
6380 bool lp_invert_boolean(const char *str, const char **inverse_str)
6381 {
6382         bool val;
6383
6384         if (!set_boolean(&val, str)) {
6385                 return False;
6386         }
6387
6388         *inverse_str = get_boolean(!val);
6389         return True;
6390 }
6391
6392 /***************************************************************************
6393  Provide the canonical string representation of a boolean value given
6394  as a string. Return True on success, False if the string given does
6395  not correctly represent a boolean.
6396 ***************************************************************************/
6397
6398 bool lp_canonicalize_boolean(const char *str, const char**canon_str)
6399 {
6400         bool val;
6401
6402         if (!set_boolean(&val, str)) {
6403                 return False;
6404         }
6405
6406         *canon_str = get_boolean(val);
6407         return True;
6408 }
6409
6410 /***************************************************************************
6411 Find a service by name. Otherwise works like get_service.
6412 ***************************************************************************/
6413
6414 static int getservicebyname(const char *pszServiceName, struct service *pserviceDest)
6415 {
6416         int iService = -1;
6417         char *canon_name;
6418         TDB_DATA data;
6419
6420         if (ServiceHash == NULL) {
6421                 return -1;
6422         }
6423
6424         canon_name = canonicalize_servicename(pszServiceName);
6425
6426         data = dbwrap_fetch_bystring(ServiceHash, canon_name, canon_name);
6427
6428         if ((data.dptr != NULL) && (data.dsize == sizeof(iService))) {
6429                 iService = *(int *)data.dptr;
6430         }
6431
6432         TALLOC_FREE(canon_name);
6433
6434         if ((iService != -1) && (LP_SNUM_OK(iService))
6435             && (pserviceDest != NULL)) {
6436                 copy_service(pserviceDest, ServicePtrs[iService], NULL);
6437         }
6438
6439         return (iService);
6440 }
6441
6442 /***************************************************************************
6443  Copy a service structure to another.
6444  If pcopymapDest is NULL then copy all fields
6445 ***************************************************************************/
6446
6447 /**
6448  * Add a parametric option to a param_opt_struct,
6449  * replacing old value, if already present.
6450  */
6451 static void set_param_opt(struct param_opt_struct **opt_list,
6452                           const char *opt_name,
6453                           const char *opt_value)
6454 {
6455         struct param_opt_struct *new_opt, *opt;
6456         bool not_added;
6457
6458         if (opt_list == NULL) {
6459                 return;
6460         }
6461
6462         opt = *opt_list;
6463         not_added = true;
6464
6465         /* Traverse destination */
6466         while (opt) {
6467                 /* If we already have same option, override it */
6468                 if (strwicmp(opt->key, opt_name) == 0) {
6469                         string_free(&opt->value);
6470                         TALLOC_FREE(opt->list);
6471                         opt->value = SMB_STRDUP(opt_value);
6472                         not_added = false;
6473                         break;
6474                 }
6475                 opt = opt->next;
6476         }
6477         if (not_added) {
6478             new_opt = SMB_XMALLOC_P(struct param_opt_struct);
6479             new_opt->key = SMB_STRDUP(opt_name);
6480             new_opt->value = SMB_STRDUP(opt_value);
6481             new_opt->list = NULL;
6482             DLIST_ADD(*opt_list, new_opt);
6483         }
6484 }
6485
6486 static void copy_service(struct service *pserviceDest, struct service *pserviceSource,
6487                          struct bitmap *pcopymapDest)
6488 {
6489         int i;
6490         bool bcopyall = (pcopymapDest == NULL);
6491         struct param_opt_struct *data;
6492
6493         for (i = 0; parm_table[i].label; i++)
6494                 if (parm_table[i].ptr && parm_table[i].p_class == P_LOCAL &&
6495                     (bcopyall || bitmap_query(pcopymapDest,i))) {
6496                         void *def_ptr = parm_table[i].ptr;
6497                         void *src_ptr =
6498                                 ((char *)pserviceSource) + PTR_DIFF(def_ptr,
6499                                                                     &sDefault);
6500                         void *dest_ptr =
6501                                 ((char *)pserviceDest) + PTR_DIFF(def_ptr,
6502                                                                   &sDefault);
6503
6504                         switch (parm_table[i].type) {
6505                                 case P_BOOL:
6506                                 case P_BOOLREV:
6507                                         *(bool *)dest_ptr = *(bool *)src_ptr;
6508                                         break;
6509
6510                                 case P_INTEGER:
6511                                 case P_ENUM:
6512                                 case P_OCTAL:
6513                                         *(int *)dest_ptr = *(int *)src_ptr;
6514                                         break;
6515
6516                                 case P_CHAR:
6517                                         *(char *)dest_ptr = *(char *)src_ptr;
6518                                         break;
6519
6520                                 case P_STRING:
6521                                         string_set((char **)dest_ptr,
6522                                                    *(char **)src_ptr);
6523                                         break;
6524
6525                                 case P_USTRING:
6526                                         string_set((char **)dest_ptr,
6527                                                    *(char **)src_ptr);
6528                                         strupper_m(*(char **)dest_ptr);
6529                                         break;
6530                                 case P_LIST:
6531                                         TALLOC_FREE(*((char ***)dest_ptr));
6532                                         *((char ***)dest_ptr) = str_list_copy(NULL, 
6533                                                       *(const char ***)src_ptr);
6534                                         break;
6535                                 default:
6536                                         break;
6537                         }
6538                 }
6539
6540         if (bcopyall) {
6541                 init_copymap(pserviceDest);
6542                 if (pserviceSource->copymap)
6543                         bitmap_copy(pserviceDest->copymap,
6544                                     pserviceSource->copymap);
6545         }
6546         
6547         data = pserviceSource->param_opt;
6548         while (data) {
6549                 set_param_opt(&pserviceDest->param_opt, data->key, data->value);
6550                 data = data->next;
6551         }
6552 }
6553
6554 /***************************************************************************
6555 Check a service for consistency. Return False if the service is in any way
6556 incomplete or faulty, else True.
6557 ***************************************************************************/
6558
6559 bool service_ok(int iService)
6560 {
6561         bool bRetval;
6562
6563         bRetval = True;
6564         if (ServicePtrs[iService]->szService[0] == '\0') {
6565                 DEBUG(0, ("The following message indicates an internal error:\n"));
6566                 DEBUG(0, ("No service name in service entry.\n"));
6567                 bRetval = False;
6568         }
6569
6570         /* The [printers] entry MUST be printable. I'm all for flexibility, but */
6571         /* I can't see why you'd want a non-printable printer service...        */
6572         if (strwicmp(ServicePtrs[iService]->szService, PRINTERS_NAME) == 0) {
6573                 if (!ServicePtrs[iService]->bPrint_ok) {
6574                         DEBUG(0, ("WARNING: [%s] service MUST be printable!\n",
6575                                ServicePtrs[iService]->szService));
6576                         ServicePtrs[iService]->bPrint_ok = True;
6577                 }
6578                 /* [printers] service must also be non-browsable. */
6579                 if (ServicePtrs[iService]->bBrowseable)
6580                         ServicePtrs[iService]->bBrowseable = False;
6581         }
6582
6583         if (ServicePtrs[iService]->szPath[0] == '\0' &&
6584             strwicmp(ServicePtrs[iService]->szService, HOMES_NAME) != 0 &&
6585             ServicePtrs[iService]->szMSDfsProxy[0] == '\0'
6586             ) {
6587                 DEBUG(0, ("WARNING: No path in service %s - making it unavailable!\n",
6588                         ServicePtrs[iService]->szService));
6589                 ServicePtrs[iService]->bAvailable = False;
6590         }
6591
6592         /* If a service is flagged unavailable, log the fact at level 1. */
6593         if (!ServicePtrs[iService]->bAvailable)
6594                 DEBUG(1, ("NOTE: Service %s is flagged unavailable.\n",
6595                           ServicePtrs[iService]->szService));
6596
6597         return (bRetval);
6598 }
6599
6600 static struct smbconf_ctx *lp_smbconf_ctx(void)
6601 {
6602         WERROR werr;
6603         static struct smbconf_ctx *conf_ctx = NULL;
6604
6605         if (conf_ctx == NULL) {
6606                 werr = smbconf_init(NULL, &conf_ctx, "registry:");
6607                 if (!W_ERROR_IS_OK(werr)) {
6608                         DEBUG(1, ("error initializing registry configuration: "
6609                                   "%s\n", dos_errstr(werr)));
6610                         conf_ctx = NULL;
6611                 }
6612         }
6613
6614         return conf_ctx;
6615 }
6616
6617 static bool process_smbconf_service(struct smbconf_service *service)
6618 {
6619         uint32_t count;
6620         bool ret;
6621
6622         if (service == NULL) {
6623                 return false;
6624         }
6625
6626         ret = do_section(service->name, NULL);
6627         if (ret != true) {
6628                 return false;
6629         }
6630         for (count = 0; count < service->num_params; count++) {
6631                 ret = do_parameter(service->param_names[count],
6632                                    service->param_values[count],
6633                                    NULL);
6634                 if (ret != true) {
6635                         return false;
6636                 }
6637         }
6638         return true;
6639 }
6640
6641 /*
6642  * process_registry_globals
6643  */
6644 static bool process_registry_globals(void)
6645 {
6646         WERROR werr;
6647         struct smbconf_service *service = NULL;
6648         TALLOC_CTX *mem_ctx = talloc_stackframe();
6649         struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
6650         bool ret = false;
6651
6652         if (conf_ctx == NULL) {
6653                 goto done;
6654         }
6655
6656         ret = do_parameter("registry shares", "yes", NULL);
6657         if (!ret) {
6658                 goto done;
6659         }
6660
6661         if (!smbconf_share_exists(conf_ctx, GLOBAL_NAME)) {
6662                 /* nothing to read from the registry yet but make sure lp_load
6663                  * doesn't return false */
6664                 ret = true;
6665                 goto done;
6666         }
6667
6668         werr = smbconf_get_share(conf_ctx, mem_ctx, GLOBAL_NAME, &service);
6669         if (!W_ERROR_IS_OK(werr)) {
6670                 goto done;
6671         }
6672
6673         ret = process_smbconf_service(service);
6674         if (!ret) {
6675                 goto done;
6676         }
6677
6678         /* store the csn */
6679         smbconf_changed(conf_ctx, &conf_last_csn, NULL, NULL);
6680
6681 done:
6682         TALLOC_FREE(mem_ctx);
6683         return ret;
6684 }
6685
6686 static bool process_registry_shares(void)
6687 {
6688         WERROR werr;
6689         uint32_t count;
6690         struct smbconf_service **service = NULL;
6691         uint32_t num_shares = 0;
6692         TALLOC_CTX *mem_ctx = talloc_stackframe();
6693         struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
6694         bool ret = false;
6695
6696         if (conf_ctx == NULL) {
6697                 goto done;
6698         }
6699
6700         werr = smbconf_get_config(conf_ctx, mem_ctx, &num_shares, &service);
6701         if (!W_ERROR_IS_OK(werr)) {
6702                 goto done;
6703         }
6704
6705         ret = true;
6706
6707         for (count = 0; count < num_shares; count++) {
6708                 if (strequal(service[count]->name, GLOBAL_NAME)) {
6709                         continue;
6710                 }
6711                 ret = process_smbconf_service(service[count]);
6712                 if (!ret) {
6713                         goto done;
6714                 }
6715         }
6716
6717         /* store the csn */
6718         smbconf_changed(conf_ctx, &conf_last_csn, NULL, NULL);
6719
6720 done:
6721         TALLOC_FREE(mem_ctx);
6722         return ret;
6723 }
6724
6725 static struct file_lists {
6726         struct file_lists *next;
6727         char *name;
6728         char *subfname;
6729         time_t modtime;
6730 } *file_lists = NULL;
6731
6732 /*******************************************************************
6733  Keep a linked list of all config files so we know when one has changed 
6734  it's date and needs to be reloaded.
6735 ********************************************************************/
6736
6737 static void add_to_file_list(const char *fname, const char *subfname)
6738 {
6739         struct file_lists *f = file_lists;
6740
6741         while (f) {
6742                 if (f->name && !strcmp(f->name, fname))
6743                         break;
6744                 f = f->next;
6745         }
6746
6747         if (!f) {
6748                 f = SMB_MALLOC_P(struct file_lists);
6749                 if (!f)
6750                         return;
6751                 f->next = file_lists;
6752                 f->name = SMB_STRDUP(fname);
6753                 if (!f->name) {
6754                         SAFE_FREE(f);
6755                         return;
6756                 }
6757                 f->subfname = SMB_STRDUP(subfname);
6758                 if (!f->subfname) {
6759                         SAFE_FREE(f);
6760                         return;
6761                 }
6762                 file_lists = f;
6763                 f->modtime = file_modtime(subfname);
6764         } else {
6765                 time_t t = file_modtime(subfname);
6766                 if (t)
6767                         f->modtime = t;
6768         }
6769 }
6770
6771 /**
6772  * Utility function for outsiders to check if we're running on registry.
6773  */
6774 bool lp_config_backend_is_registry(void)
6775 {
6776         return (lp_config_backend() == CONFIG_BACKEND_REGISTRY);
6777 }
6778
6779 /**
6780  * Utility function to check if the config backend is FILE.
6781  */
6782 bool lp_config_backend_is_file(void)
6783 {
6784         return (lp_config_backend() == CONFIG_BACKEND_FILE);
6785 }
6786
6787 /*******************************************************************
6788  Check if a config file has changed date.
6789 ********************************************************************/
6790
6791 bool lp_file_list_changed(void)
6792 {
6793         struct file_lists *f = file_lists;
6794
6795         DEBUG(6, ("lp_file_list_changed()\n"));
6796
6797         if (lp_config_backend_is_registry()) {
6798                 struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
6799
6800                 if (conf_ctx == NULL) {
6801                         return false;
6802                 }
6803                 if (smbconf_changed(conf_ctx, &conf_last_csn, NULL, NULL)) {
6804                         DEBUGADD(6, ("registry config changed\n"));
6805                         return true;
6806                 }
6807         }
6808
6809         while (f) {
6810                 char *n2 = NULL;
6811                 time_t mod_time;
6812
6813                 n2 = alloc_sub_basic(get_current_username(),
6814                                     current_user_info.domain,
6815                                     f->name);
6816                 if (!n2) {
6817                         return false;
6818                 }
6819                 DEBUGADD(6, ("file %s -> %s  last mod_time: %s\n",
6820                              f->name, n2, ctime(&f->modtime)));
6821
6822                 mod_time = file_modtime(n2);
6823
6824                 if (mod_time && ((f->modtime != mod_time) || (f->subfname == NULL) || (strcmp(n2, f->subfname) != 0))) {
6825                         DEBUGADD(6,
6826                                  ("file %s modified: %s\n", n2,
6827                                   ctime(&mod_time)));
6828                         f->modtime = mod_time;
6829                         SAFE_FREE(f->subfname);
6830                         f->subfname = n2; /* Passing ownership of
6831                                              return from alloc_sub_basic
6832                                              above. */
6833                         return true;
6834                 }
6835                 SAFE_FREE(n2);
6836                 f = f->next;
6837         }
6838         return (False);
6839 }
6840
6841
6842 /***************************************************************************
6843  Run standard_sub_basic on netbios name... needed because global_myname
6844  is not accessed through any lp_ macro.
6845  Note: We must *NOT* use string_set() here as ptr points to global_myname.
6846 ***************************************************************************/
6847
6848 static bool handle_netbios_name(int snum, const char *pszParmValue, char **ptr)
6849 {
6850         bool ret;
6851         char *netbios_name = alloc_sub_basic(get_current_username(),
6852                                         current_user_info.domain,
6853                                         pszParmValue);
6854
6855         ret = set_global_myname(netbios_name);
6856         SAFE_FREE(netbios_name);
6857         string_set(&Globals.szNetbiosName,global_myname());
6858
6859         DEBUG(4, ("handle_netbios_name: set global_myname to: %s\n",
6860                global_myname()));
6861
6862         return ret;
6863 }
6864
6865 static bool handle_charset(int snum, const char *pszParmValue, char **ptr)
6866 {
6867         if (strcmp(*ptr, pszParmValue) != 0) {
6868                 string_set(ptr, pszParmValue);
6869                 init_iconv();
6870         }
6871         return True;
6872 }
6873
6874
6875
6876 static bool handle_workgroup(int snum, const char *pszParmValue, char **ptr)
6877 {
6878         bool ret;
6879         
6880         ret = set_global_myworkgroup(pszParmValue);
6881         string_set(&Globals.szWorkgroup,lp_workgroup());
6882         
6883         return ret;
6884 }
6885
6886 static bool handle_netbios_scope(int snum, const char *pszParmValue, char **ptr)
6887 {
6888         bool ret;
6889         
6890         ret = set_global_scope(pszParmValue);
6891         string_set(&Globals.szNetbiosScope,global_scope());
6892
6893         return ret;
6894 }
6895
6896 static bool handle_netbios_aliases(int snum, const char *pszParmValue, char **ptr)
6897 {
6898         TALLOC_FREE(Globals.szNetbiosAliases);
6899         Globals.szNetbiosAliases = str_list_make(NULL, pszParmValue, NULL);
6900         return set_netbios_aliases((const char **)Globals.szNetbiosAliases);
6901 }
6902
6903 /***************************************************************************
6904  Handle the include operation.
6905 ***************************************************************************/
6906 static bool bAllowIncludeRegistry = true;
6907
6908 static bool handle_include(int snum, const char *pszParmValue, char **ptr)
6909 {
6910         char *fname;
6911
6912         if (strequal(pszParmValue, INCLUDE_REGISTRY_NAME)) {
6913                 if (!bAllowIncludeRegistry) {
6914                         return true;
6915                 }
6916                 if (bInGlobalSection) {
6917                         return process_registry_globals();
6918                 } else {
6919                         DEBUG(1, ("\"include = registry\" only effective "
6920                                   "in %s section\n", GLOBAL_NAME));
6921                         return false;
6922                 }
6923         }
6924
6925         fname = alloc_sub_basic(get_current_username(),
6926                                 current_user_info.domain,
6927                                 pszParmValue);
6928
6929         add_to_file_list(pszParmValue, fname);
6930
6931         string_set(ptr, fname);
6932
6933         if (file_exist(fname, NULL)) {
6934                 bool ret = pm_process(fname, do_section, do_parameter, NULL);
6935                 SAFE_FREE(fname);
6936                 return ret;
6937         }
6938
6939         DEBUG(2, ("Can't find include file %s\n", fname));
6940         SAFE_FREE(fname);
6941         return true;
6942 }
6943
6944 /***************************************************************************
6945  Handle the interpretation of the copy parameter.
6946 ***************************************************************************/
6947
6948 static bool handle_copy(int snum, const char *pszParmValue, char **ptr)
6949 {
6950         bool bRetval;
6951         int iTemp;
6952         struct service serviceTemp;
6953
6954         string_set(ptr, pszParmValue);
6955
6956         init_service(&serviceTemp);
6957
6958         bRetval = False;
6959
6960         DEBUG(3, ("Copying service from service %s\n", pszParmValue));
6961
6962         if ((iTemp = getservicebyname(pszParmValue, &serviceTemp)) >= 0) {
6963                 if (iTemp == iServiceIndex) {
6964                         DEBUG(0, ("Can't copy service %s - unable to copy self!\n", pszParmValue));
6965                 } else {
6966                         copy_service(ServicePtrs[iServiceIndex],
6967                                      &serviceTemp,
6968                                      ServicePtrs[iServiceIndex]->copymap);
6969                         bRetval = True;
6970                 }
6971         } else {
6972                 DEBUG(0, ("Unable to copy service - source not found: %s\n", pszParmValue));
6973                 bRetval = False;
6974         }
6975
6976         free_service(&serviceTemp);
6977         return (bRetval);
6978 }
6979
6980 static bool handle_ldap_debug_level(int snum, const char *pszParmValue, char **ptr)
6981 {
6982         Globals.ldap_debug_level = lp_int(pszParmValue);
6983         init_ldap_debugging();
6984         return true;
6985 }
6986
6987 /***************************************************************************
6988  Handle idmap/non unix account uid and gid allocation parameters.  The format of these
6989  parameters is:
6990
6991  [global]
6992
6993         idmap uid = 1000-1999
6994         idmap gid = 700-899
6995
6996  We only do simple parsing checks here.  The strings are parsed into useful
6997  structures in the idmap daemon code.
6998
6999 ***************************************************************************/
7000
7001 /* Some lp_ routines to return idmap [ug]id information */
7002
7003 static uid_t idmap_uid_low, idmap_uid_high;
7004 static gid_t idmap_gid_low, idmap_gid_high;
7005
7006 bool lp_idmap_uid(uid_t *low, uid_t *high)
7007 {
7008         if (idmap_uid_low == 0 || idmap_uid_high == 0)
7009                 return False;
7010
7011         if (low)
7012                 *low = idmap_uid_low;
7013
7014         if (high)
7015                 *high = idmap_uid_high;
7016
7017         return True;
7018 }
7019
7020 bool lp_idmap_gid(gid_t *low, gid_t *high)
7021 {
7022         if (idmap_gid_low == 0 || idmap_gid_high == 0)
7023                 return False;
7024
7025         if (low)
7026                 *low = idmap_gid_low;
7027
7028         if (high)
7029                 *high = idmap_gid_high;
7030
7031         return True;
7032 }
7033
7034 /* Do some simple checks on "idmap [ug]id" parameter values */
7035
7036 static bool handle_idmap_uid(int snum, const char *pszParmValue, char **ptr)
7037 {
7038         uint32 low, high;
7039
7040         if (sscanf(pszParmValue, "%u - %u", &low, &high) != 2 || high < low)
7041                 return False;
7042
7043         /* Parse OK */
7044
7045         string_set(ptr, pszParmValue);
7046
7047         idmap_uid_low = low;
7048         idmap_uid_high = high;
7049
7050         return True;
7051 }
7052
7053 static bool handle_idmap_gid(int snum, const char *pszParmValue, char **ptr)
7054 {
7055         uint32 low, high;
7056
7057         if (sscanf(pszParmValue, "%u - %u", &low, &high) != 2 || high < low)
7058                 return False;
7059
7060         /* Parse OK */
7061
7062         string_set(ptr, pszParmValue);
7063
7064         idmap_gid_low = low;
7065         idmap_gid_high = high;
7066
7067         return True;
7068 }
7069
7070 /***************************************************************************
7071  Handle the DEBUG level list.
7072 ***************************************************************************/
7073
7074 static bool handle_debug_list( int snum, const char *pszParmValueIn, char **ptr )
7075 {
7076         string_set(ptr, pszParmValueIn);
7077         return debug_parse_levels(pszParmValueIn);
7078 }
7079
7080 /***************************************************************************
7081  Handle ldap suffixes - default to ldapsuffix if sub-suffixes are not defined.
7082 ***************************************************************************/
7083
7084 static const char *append_ldap_suffix( const char *str )
7085 {
7086         const char *suffix_string;
7087
7088
7089         suffix_string = talloc_asprintf(talloc_tos(), "%s,%s", str,
7090                                         Globals.szLdapSuffix );
7091         if ( !suffix_string ) {
7092                 DEBUG(0,("append_ldap_suffix: talloc_asprintf() failed!\n"));
7093                 return "";
7094         }
7095
7096         return suffix_string;
7097 }
7098
7099 const char *lp_ldap_machine_suffix(void)
7100 {
7101         if (Globals.szLdapMachineSuffix[0])
7102                 return append_ldap_suffix(Globals.szLdapMachineSuffix);
7103
7104         return lp_string(Globals.szLdapSuffix);
7105 }
7106
7107 const char *lp_ldap_user_suffix(void)
7108 {
7109         if (Globals.szLdapUserSuffix[0])
7110                 return append_ldap_suffix(Globals.szLdapUserSuffix);
7111
7112         return lp_string(Globals.szLdapSuffix);
7113 }
7114
7115 const char *lp_ldap_group_suffix(void)
7116 {
7117         if (Globals.szLdapGroupSuffix[0])
7118                 return append_ldap_suffix(Globals.szLdapGroupSuffix);
7119
7120         return lp_string(Globals.szLdapSuffix);
7121 }
7122
7123 const char *lp_ldap_idmap_suffix(void)
7124 {
7125         if (Globals.szLdapIdmapSuffix[0])
7126                 return append_ldap_suffix(Globals.szLdapIdmapSuffix);
7127
7128         return lp_string(Globals.szLdapSuffix);
7129 }
7130
7131 /****************************************************************************
7132  set the value for a P_ENUM
7133  ***************************************************************************/
7134
7135 static void lp_set_enum_parm( struct parm_struct *parm, const char *pszParmValue,
7136                               int *ptr )
7137 {
7138         int i;
7139
7140         for (i = 0; parm->enum_list[i].name; i++) {
7141                 if ( strequal(pszParmValue, parm->enum_list[i].name)) {
7142                         *ptr = parm->enum_list[i].value;
7143                         return;
7144                 }
7145         }
7146         DEBUG(0, ("WARNING: Ignoring invalid value '%s' for parameter '%s'\n",
7147                   pszParmValue, parm->label));
7148 }
7149
7150 /***************************************************************************
7151 ***************************************************************************/
7152
7153 static bool handle_printing(int snum, const char *pszParmValue, char **ptr)
7154 {
7155         static int parm_num = -1;
7156         struct service *s;
7157
7158         if ( parm_num == -1 )
7159                 parm_num = map_parameter( "printing" );
7160
7161         lp_set_enum_parm( &parm_table[parm_num], pszParmValue, (int*)ptr );
7162
7163         if ( snum < 0 )
7164                 s = &sDefault;
7165         else
7166                 s = ServicePtrs[snum];
7167
7168         init_printer_values( s );
7169
7170         return True;
7171 }
7172
7173
7174 /***************************************************************************
7175  Initialise a copymap.
7176 ***************************************************************************/
7177
7178 static void init_copymap(struct service *pservice)
7179 {
7180         int i;
7181         if (pservice->copymap) {
7182                 bitmap_free(pservice->copymap);
7183         }
7184         pservice->copymap = bitmap_allocate(NUMPARAMETERS);
7185         if (!pservice->copymap)
7186                 DEBUG(0,
7187                       ("Couldn't allocate copymap!! (size %d)\n",
7188                        (int)NUMPARAMETERS));
7189         else
7190                 for (i = 0; i < NUMPARAMETERS; i++)
7191                         bitmap_set(pservice->copymap, i);
7192 }
7193
7194 /***************************************************************************
7195  Return the local pointer to a parameter given the service number and the 
7196  pointer into the default structure.
7197 ***************************************************************************/
7198
7199 void *lp_local_ptr(int snum, void *ptr)
7200 {
7201         return (void *)(((char *)ServicePtrs[snum]) + PTR_DIFF(ptr, &sDefault));
7202 }
7203
7204 /***************************************************************************
7205  Process a parameter for a particular service number. If snum < 0
7206  then assume we are in the globals.
7207 ***************************************************************************/
7208
7209 bool lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue)
7210 {
7211         int parmnum, i;
7212         void *parm_ptr = NULL;  /* where we are going to store the result */
7213         void *def_ptr = NULL;
7214         struct param_opt_struct **opt_list;
7215
7216         parmnum = map_parameter(pszParmName);
7217
7218         if (parmnum < 0) {
7219                 if (strchr(pszParmName, ':') == NULL) {
7220                         DEBUG(0, ("Ignoring unknown parameter \"%s\"\n",
7221                                   pszParmName));
7222                         return (True);
7223                 }
7224
7225                 /*
7226                  * We've got a parametric option
7227                  */
7228
7229                 opt_list = (snum < 0)
7230                         ? &Globals.param_opt : &ServicePtrs[snum]->param_opt;
7231                 set_param_opt(opt_list, pszParmName, pszParmValue);
7232
7233                 return (True);
7234         }
7235
7236         if (parm_table[parmnum].flags & FLAG_DEPRECATED) {
7237                 DEBUG(1, ("WARNING: The \"%s\" option is deprecated\n",
7238                           pszParmName));
7239         }
7240
7241         def_ptr = parm_table[parmnum].ptr;
7242
7243         /* we might point at a service, the default service or a global */
7244         if (snum < 0) {
7245                 parm_ptr = def_ptr;
7246         } else {
7247                 if (parm_table[parmnum].p_class == P_GLOBAL) {
7248                         DEBUG(0,
7249                               ("Global parameter %s found in service section!\n",
7250                                pszParmName));
7251                         return (True);
7252                 }
7253                 parm_ptr = lp_local_ptr(snum, def_ptr);
7254         }
7255
7256         if (snum >= 0) {
7257                 if (!ServicePtrs[snum]->copymap)
7258                         init_copymap(ServicePtrs[snum]);
7259
7260                 /* this handles the aliases - set the copymap for other entries with
7261                    the same data pointer */
7262                 for (i = 0; parm_table[i].label; i++)
7263                         if (parm_table[i].ptr == parm_table[parmnum].ptr)
7264                                 bitmap_clear(ServicePtrs[snum]->copymap, i);
7265         }
7266
7267         /* if it is a special case then go ahead */
7268         if (parm_table[parmnum].special) {
7269                 return parm_table[parmnum].special(snum, pszParmValue,
7270                                                    (char **)parm_ptr);
7271         }
7272
7273         /* now switch on the type of variable it is */
7274         switch (parm_table[parmnum].type)
7275         {
7276                 case P_BOOL:
7277                         *(bool *)parm_ptr = lp_bool(pszParmValue);
7278                         break;
7279
7280                 case P_BOOLREV:
7281                         *(bool *)parm_ptr = !lp_bool(pszParmValue);
7282                         break;
7283
7284                 case P_INTEGER:
7285                         *(int *)parm_ptr = lp_int(pszParmValue);
7286                         break;
7287
7288                 case P_CHAR:
7289                         *(char *)parm_ptr = *pszParmValue;
7290                         break;
7291
7292                 case P_OCTAL:
7293                         i = sscanf(pszParmValue, "%o", (int *)parm_ptr);
7294                         if ( i != 1 ) {
7295                             DEBUG ( 0, ("Invalid octal number %s\n", pszParmName ));
7296                         }
7297                         break;
7298
7299                 case P_LIST:
7300                         TALLOC_FREE(*((char ***)parm_ptr));
7301                         *(char ***)parm_ptr = str_list_make(
7302                                 NULL, pszParmValue, NULL);
7303                         break;
7304
7305                 case P_STRING:
7306                         string_set((char **)parm_ptr, pszParmValue);
7307                         break;
7308
7309                 case P_USTRING:
7310                         string_set((char **)parm_ptr, pszParmValue);
7311                         strupper_m(*(char **)parm_ptr);
7312                         break;
7313
7314                 case P_ENUM:
7315                         lp_set_enum_parm( &parm_table[parmnum], pszParmValue, (int*)parm_ptr );
7316                         break;
7317                 case P_SEP:
7318                         break;
7319         }
7320
7321         return (True);
7322 }
7323
7324 /***************************************************************************
7325  Process a parameter.
7326 ***************************************************************************/
7327
7328 static bool do_parameter(const char *pszParmName, const char *pszParmValue,
7329                          void *userdata)
7330 {
7331         if (!bInGlobalSection && bGlobalOnly)
7332                 return (True);
7333
7334         DEBUGADD(4, ("doing parameter %s = %s\n", pszParmName, pszParmValue));
7335
7336         return (lp_do_parameter(bInGlobalSection ? -2 : iServiceIndex,
7337                                 pszParmName, pszParmValue));
7338 }
7339
7340 /***************************************************************************
7341  Print a parameter of the specified type.
7342 ***************************************************************************/
7343
7344 static void print_parameter(struct parm_struct *p, void *ptr, FILE * f)
7345 {
7346         int i;
7347         switch (p->type)
7348         {
7349                 case P_ENUM:
7350                         for (i = 0; p->enum_list[i].name; i++) {
7351                                 if (*(int *)ptr == p->enum_list[i].value) {
7352                                         fprintf(f, "%s",
7353                                                 p->enum_list[i].name);
7354                                         break;
7355                                 }
7356                         }
7357                         break;
7358
7359                 case P_BOOL:
7360                         fprintf(f, "%s", BOOLSTR(*(bool *)ptr));
7361                         break;
7362
7363                 case P_BOOLREV:
7364                         fprintf(f, "%s", BOOLSTR(!*(bool *)ptr));
7365                         break;
7366
7367                 case P_INTEGER:
7368                         fprintf(f, "%d", *(int *)ptr);
7369                         break;
7370
7371                 case P_CHAR:
7372                         fprintf(f, "%c", *(char *)ptr);
7373                         break;
7374
7375                 case P_OCTAL: {
7376                         char *o = octal_string(*(int *)ptr);
7377                         fprintf(f, "%s", o);
7378                         TALLOC_FREE(o);
7379                         break;
7380                 }
7381
7382                 case P_LIST:
7383                         if ((char ***)ptr && *(char ***)ptr) {
7384                                 char **list = *(char ***)ptr;
7385                                 for (; *list; list++) {
7386                                         /* surround strings with whitespace in double quotes */
7387                                         if ( strchr_m( *list, ' ' ) )
7388                                                 fprintf(f, "\"%s\"%s", *list, ((*(list+1))?", ":""));
7389                                         else
7390                                                 fprintf(f, "%s%s", *list, ((*(list+1))?", ":""));
7391                                 }
7392                         }
7393                         break;
7394
7395                 case P_STRING:
7396                 case P_USTRING:
7397                         if (*(char **)ptr) {
7398                                 fprintf(f, "%s", *(char **)ptr);
7399                         }
7400                         break;
7401                 case P_SEP:
7402                         break;
7403         }
7404 }
7405
7406 /***************************************************************************
7407  Check if two parameters are equal.
7408 ***************************************************************************/
7409
7410 static bool equal_parameter(parm_type type, void *ptr1, void *ptr2)
7411 {
7412         switch (type) {
7413                 case P_BOOL:
7414                 case P_BOOLREV:
7415                         return (*((bool *)ptr1) == *((bool *)ptr2));
7416
7417                 case P_INTEGER:
7418                 case P_ENUM:
7419                 case P_OCTAL:
7420                         return (*((int *)ptr1) == *((int *)ptr2));
7421
7422                 case P_CHAR:
7423                         return (*((char *)ptr1) == *((char *)ptr2));
7424
7425                 case P_LIST:
7426                         return str_list_compare(*(char ***)ptr1, *(char ***)ptr2);
7427
7428                 case P_STRING:
7429                 case P_USTRING:
7430                 {
7431                         char *p1 = *(char **)ptr1, *p2 = *(char **)ptr2;
7432                         if (p1 && !*p1)
7433                                 p1 = NULL;
7434                         if (p2 && !*p2)
7435                                 p2 = NULL;
7436                         return (p1 == p2 || strequal(p1, p2));
7437                 }
7438                 case P_SEP:
7439                         break;
7440         }
7441         return (False);
7442 }
7443
7444 /***************************************************************************
7445  Initialize any local varients in the sDefault table.
7446 ***************************************************************************/
7447
7448 void init_locals(void)
7449 {
7450         /* None as yet. */
7451 }
7452
7453 /***************************************************************************
7454  Process a new section (service). At this stage all sections are services.
7455  Later we'll have special sections that permit server parameters to be set.
7456  Returns True on success, False on failure. 
7457 ***************************************************************************/
7458
7459 static bool do_section(const char *pszSectionName, void *userdata)
7460 {
7461         bool bRetval;
7462         bool isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
7463                          (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
7464         bRetval = False;
7465
7466         /* if we were in a global section then do the local inits */
7467         if (bInGlobalSection && !isglobal)
7468                 init_locals();
7469
7470         /* if we've just struck a global section, note the fact. */
7471         bInGlobalSection = isglobal;
7472
7473         /* check for multiple global sections */
7474         if (bInGlobalSection) {
7475                 DEBUG(3, ("Processing section \"[%s]\"\n", pszSectionName));
7476                 return (True);
7477         }
7478
7479         if (!bInGlobalSection && bGlobalOnly)
7480                 return (True);
7481
7482         /* if we have a current service, tidy it up before moving on */
7483         bRetval = True;
7484
7485         if (iServiceIndex >= 0)
7486                 bRetval = service_ok(iServiceIndex);
7487
7488         /* if all is still well, move to the next record in the services array */
7489         if (bRetval) {
7490                 /* We put this here to avoid an odd message order if messages are */
7491                 /* issued by the post-processing of a previous section. */
7492                 DEBUG(2, ("Processing section \"[%s]\"\n", pszSectionName));
7493
7494                 if ((iServiceIndex = add_a_service(&sDefault, pszSectionName))
7495                     < 0) {
7496                         DEBUG(0, ("Failed to add a new service\n"));
7497                         return (False);
7498                 }
7499         }
7500
7501         return (bRetval);
7502 }
7503
7504
7505 /***************************************************************************
7506  Determine if a partcular base parameter is currentl set to the default value.
7507 ***************************************************************************/
7508
7509 static bool is_default(int i)
7510 {
7511         if (!defaults_saved)
7512                 return False;
7513         switch (parm_table[i].type) {
7514                 case P_LIST:
7515                         return str_list_compare (parm_table[i].def.lvalue, 
7516                                                 *(char ***)parm_table[i].ptr);
7517                 case P_STRING:
7518                 case P_USTRING:
7519                         return strequal(parm_table[i].def.svalue,
7520                                         *(char **)parm_table[i].ptr);
7521                 case P_BOOL:
7522                 case P_BOOLREV:
7523                         return parm_table[i].def.bvalue ==
7524                                 *(bool *)parm_table[i].ptr;
7525                 case P_CHAR:
7526                         return parm_table[i].def.cvalue ==
7527                                 *(char *)parm_table[i].ptr;
7528                 case P_INTEGER:
7529                 case P_OCTAL:
7530                 case P_ENUM:
7531                         return parm_table[i].def.ivalue ==
7532                                 *(int *)parm_table[i].ptr;
7533                 case P_SEP:
7534                         break;
7535         }
7536         return False;
7537 }
7538
7539 /***************************************************************************
7540 Display the contents of the global structure.
7541 ***************************************************************************/
7542
7543 static void dump_globals(FILE *f)
7544 {
7545         int i;
7546         struct param_opt_struct *data;
7547         
7548         fprintf(f, "[global]\n");
7549
7550         for (i = 0; parm_table[i].label; i++)
7551                 if (parm_table[i].p_class == P_GLOBAL &&
7552                     parm_table[i].ptr &&
7553                     (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) {
7554                         if (defaults_saved && is_default(i))
7555                                 continue;
7556                         fprintf(f, "\t%s = ", parm_table[i].label);
7557                         print_parameter(&parm_table[i], parm_table[i].ptr, f);
7558                         fprintf(f, "\n");
7559         }
7560         if (Globals.param_opt != NULL) {
7561                 data = Globals.param_opt;
7562                 while(data) {
7563                         fprintf(f, "\t%s = %s\n", data->key, data->value);
7564                         data = data->next;
7565                 }
7566         }
7567
7568 }
7569
7570 /***************************************************************************
7571  Return True if a local parameter is currently set to the global default.
7572 ***************************************************************************/
7573
7574 bool lp_is_default(int snum, struct parm_struct *parm)
7575 {
7576         int pdiff = PTR_DIFF(parm->ptr, &sDefault);
7577
7578         return equal_parameter(parm->type,
7579                                ((char *)ServicePtrs[snum]) + pdiff,
7580                                ((char *)&sDefault) + pdiff);
7581 }
7582
7583 /***************************************************************************
7584  Display the contents of a single services record.
7585 ***************************************************************************/
7586
7587 static void dump_a_service(struct service *pService, FILE * f)
7588 {
7589         int i;
7590         struct param_opt_struct *data;
7591         
7592         if (pService != &sDefault)
7593                 fprintf(f, "[%s]\n", pService->szService);
7594
7595         for (i = 0; parm_table[i].label; i++) {
7596
7597                 if (parm_table[i].p_class == P_LOCAL &&
7598                     parm_table[i].ptr &&
7599                     (*parm_table[i].label != '-') &&
7600                     (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) 
7601                 {
7602                 
7603                         int pdiff = PTR_DIFF(parm_table[i].ptr, &sDefault);
7604
7605                         if (pService == &sDefault) {
7606                                 if (defaults_saved && is_default(i))
7607                                         continue;
7608                         } else {
7609                                 if (equal_parameter(parm_table[i].type,
7610                                                     ((char *)pService) +
7611                                                     pdiff,
7612                                                     ((char *)&sDefault) +
7613                                                     pdiff))
7614                                         continue;
7615                         }
7616
7617                         fprintf(f, "\t%s = ", parm_table[i].label);
7618                         print_parameter(&parm_table[i],
7619                                         ((char *)pService) + pdiff, f);
7620                         fprintf(f, "\n");
7621                 }
7622         }
7623
7624                 if (pService->param_opt != NULL) {
7625                         data = pService->param_opt;
7626                         while(data) {
7627                                 fprintf(f, "\t%s = %s\n", data->key, data->value);
7628                                 data = data->next;
7629                         }
7630                 }
7631 }
7632
7633 /***************************************************************************
7634  Display the contents of a parameter of a single services record.
7635 ***************************************************************************/
7636
7637 bool dump_a_parameter(int snum, char *parm_name, FILE * f, bool isGlobal)
7638 {
7639         int i;
7640         bool result = False;
7641         parm_class p_class;
7642         unsigned flag = 0;
7643         fstring local_parm_name;
7644         char *parm_opt;
7645         const char *parm_opt_value;
7646
7647         /* check for parametrical option */
7648         fstrcpy( local_parm_name, parm_name);
7649         parm_opt = strchr( local_parm_name, ':');
7650
7651         if (parm_opt) {
7652                 *parm_opt = '\0';
7653                 parm_opt++;
7654                 if (strlen(parm_opt)) {
7655                         parm_opt_value = lp_parm_const_string( snum,
7656                                 local_parm_name, parm_opt, NULL);
7657                         if (parm_opt_value) {
7658                                 printf( "%s\n", parm_opt_value);
7659                                 result = True;
7660                         }
7661                 }
7662                 return result;
7663         }
7664
7665         /* check for a key and print the value */
7666         if (isGlobal) {
7667                 p_class = P_GLOBAL;
7668                 flag = FLAG_GLOBAL;
7669         } else
7670                 p_class = P_LOCAL;
7671
7672         for (i = 0; parm_table[i].label; i++) {
7673                 if (strwicmp(parm_table[i].label, parm_name) == 0 &&
7674                     (parm_table[i].p_class == p_class || parm_table[i].flags & flag) &&
7675                     parm_table[i].ptr &&
7676                     (*parm_table[i].label != '-') &&
7677                     (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) 
7678                 {
7679                         void *ptr;
7680
7681                         if (isGlobal) {
7682                                 ptr = parm_table[i].ptr;
7683                         } else {
7684                                 struct service *pService = ServicePtrs[snum];
7685                                 ptr = ((char *)pService) +
7686                                         PTR_DIFF(parm_table[i].ptr, &sDefault);
7687                         }
7688
7689                         print_parameter(&parm_table[i],
7690                                         ptr, f);
7691                         fprintf(f, "\n");
7692                         result = True;
7693                         break;
7694                 }
7695         }
7696
7697         return result;
7698 }
7699
7700 /***************************************************************************
7701  Return info about the requested parameter (given as a string).
7702  Return NULL when the string is not a valid parameter name.
7703 ***************************************************************************/
7704
7705 struct parm_struct *lp_get_parameter(const char *param_name)
7706 {
7707         int num = map_parameter(param_name);
7708
7709         if (num < 0) {
7710                 return NULL;
7711         }
7712
7713         return &parm_table[num];
7714 }
7715
7716 /***************************************************************************
7717  Return info about the next parameter in a service.
7718  snum==GLOBAL_SECTION_SNUM gives the globals.
7719  Return NULL when out of parameters.
7720 ***************************************************************************/
7721
7722 struct parm_struct *lp_next_parameter(int snum, int *i, int allparameters)
7723 {
7724         if (snum < 0) {
7725                 /* do the globals */
7726                 for (; parm_table[*i].label; (*i)++) {
7727                         if (parm_table[*i].p_class == P_SEPARATOR)
7728                                 return &parm_table[(*i)++];
7729
7730                         if (!parm_table[*i].ptr
7731                             || (*parm_table[*i].label == '-'))
7732                                 continue;
7733
7734                         if ((*i) > 0
7735                             && (parm_table[*i].ptr ==
7736                                 parm_table[(*i) - 1].ptr))
7737                                 continue;
7738                         
7739                         if (is_default(*i) && !allparameters)
7740                                 continue;
7741
7742                         return &parm_table[(*i)++];
7743                 }
7744         } else {
7745                 struct service *pService = ServicePtrs[snum];
7746
7747                 for (; parm_table[*i].label; (*i)++) {
7748                         if (parm_table[*i].p_class == P_SEPARATOR)
7749                                 return &parm_table[(*i)++];
7750
7751                         if (parm_table[*i].p_class == P_LOCAL &&
7752                             parm_table[*i].ptr &&
7753                             (*parm_table[*i].label != '-') &&
7754                             ((*i) == 0 ||
7755                              (parm_table[*i].ptr !=
7756                               parm_table[(*i) - 1].ptr)))
7757                         {
7758                                 int pdiff =
7759                                         PTR_DIFF(parm_table[*i].ptr,
7760                                                  &sDefault);
7761
7762                                 if (allparameters ||
7763                                     !equal_parameter(parm_table[*i].type,
7764                                                      ((char *)pService) +
7765                                                      pdiff,
7766                                                      ((char *)&sDefault) +
7767                                                      pdiff))
7768                                 {
7769                                         return &parm_table[(*i)++];
7770                                 }
7771                         }
7772                 }
7773         }
7774
7775         return NULL;
7776 }
7777
7778
7779 #if 0
7780 /***************************************************************************
7781  Display the contents of a single copy structure.
7782 ***************************************************************************/
7783 static void dump_copy_map(bool *pcopymap)
7784 {
7785         int i;
7786         if (!pcopymap)
7787                 return;
7788
7789         printf("\n\tNon-Copied parameters:\n");
7790
7791         for (i = 0; parm_table[i].label; i++)
7792                 if (parm_table[i].p_class == P_LOCAL &&
7793                     parm_table[i].ptr && !pcopymap[i] &&
7794                     (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr)))
7795                 {
7796                         printf("\t\t%s\n", parm_table[i].label);
7797                 }
7798 }
7799 #endif
7800
7801 /***************************************************************************
7802  Return TRUE if the passed service number is within range.
7803 ***************************************************************************/
7804
7805 bool lp_snum_ok(int iService)
7806 {
7807         return (LP_SNUM_OK(iService) && ServicePtrs[iService]->bAvailable);
7808 }
7809
7810 /***************************************************************************
7811  Auto-load some home services.
7812 ***************************************************************************/
7813
7814 static void lp_add_auto_services(char *str)
7815 {
7816         char *s;
7817         char *p;
7818         int homes;
7819         char *saveptr;
7820
7821         if (!str)
7822                 return;
7823
7824         s = SMB_STRDUP(str);
7825         if (!s)
7826                 return;
7827
7828         homes = lp_servicenumber(HOMES_NAME);
7829
7830         for (p = strtok_r(s, LIST_SEP, &saveptr); p;
7831              p = strtok_r(NULL, LIST_SEP, &saveptr)) {
7832                 char *home;
7833
7834                 if (lp_servicenumber(p) >= 0)
7835                         continue;
7836
7837                 home = get_user_home_dir(talloc_tos(), p);
7838
7839                 if (home && homes >= 0)
7840                         lp_add_home(p, homes, p, home);
7841
7842                 TALLOC_FREE(home);
7843         }
7844         SAFE_FREE(s);
7845 }
7846
7847 /***************************************************************************
7848  Auto-load one printer.
7849 ***************************************************************************/
7850
7851 void lp_add_one_printer(const char *name, const char *comment, void *pdata)
7852 {
7853         int printers = lp_servicenumber(PRINTERS_NAME);
7854         int i;
7855
7856         if (lp_servicenumber(name) < 0) {
7857                 lp_add_printer(name, printers);
7858                 if ((i = lp_servicenumber(name)) >= 0) {
7859                         string_set(&ServicePtrs[i]->comment, comment);
7860                         ServicePtrs[i]->autoloaded = True;
7861                 }
7862         }
7863 }
7864
7865 /***************************************************************************
7866  Have we loaded a services file yet?
7867 ***************************************************************************/
7868
7869 bool lp_loaded(void)
7870 {
7871         return (bLoaded);
7872 }
7873
7874 /***************************************************************************
7875  Unload unused services.
7876 ***************************************************************************/
7877
7878 void lp_killunused(bool (*snumused) (int))
7879 {
7880         int i;
7881         for (i = 0; i < iNumServices; i++) {
7882                 if (!VALID(i))
7883                         continue;
7884
7885                 /* don't kill autoloaded or usershare services */
7886                 if ( ServicePtrs[i]->autoloaded ||
7887                                 ServicePtrs[i]->usershare == USERSHARE_VALID) {
7888                         continue;
7889                 }
7890
7891                 if (!snumused || !snumused(i)) {
7892                         free_service_byindex(i);
7893                 }
7894         }
7895 }
7896
7897 /**
7898  * Kill all except autoloaded and usershare services - convenience wrapper
7899  */
7900 void lp_kill_all_services(void)
7901 {
7902         lp_killunused(NULL);
7903 }
7904
7905 /***************************************************************************
7906  Unload a service.
7907 ***************************************************************************/
7908
7909 void lp_killservice(int iServiceIn)
7910 {
7911         if (VALID(iServiceIn)) {
7912                 free_service_byindex(iServiceIn);
7913         }
7914 }
7915
7916 /***************************************************************************
7917  Save the curent values of all global and sDefault parameters into the 
7918  defaults union. This allows swat and testparm to show only the
7919  changed (ie. non-default) parameters.
7920 ***************************************************************************/
7921
7922 static void lp_save_defaults(void)
7923 {
7924         int i;
7925         for (i = 0; parm_table[i].label; i++) {
7926                 if (i > 0 && parm_table[i].ptr == parm_table[i - 1].ptr)
7927                         continue;
7928                 switch (parm_table[i].type) {
7929                         case P_LIST:
7930                                 parm_table[i].def.lvalue = str_list_copy(
7931                                         NULL, *(const char ***)parm_table[i].ptr);
7932                                 break;
7933                         case P_STRING:
7934                         case P_USTRING:
7935                                 if (parm_table[i].ptr) {
7936                                         parm_table[i].def.svalue = SMB_STRDUP(*(char **)parm_table[i].ptr);
7937                                 } else {
7938                                         parm_table[i].def.svalue = NULL;
7939                                 }
7940                                 break;
7941                         case P_BOOL:
7942                         case P_BOOLREV:
7943                                 parm_table[i].def.bvalue =
7944                                         *(bool *)parm_table[i].ptr;
7945                                 break;
7946                         case P_CHAR:
7947                                 parm_table[i].def.cvalue =
7948                                         *(char *)parm_table[i].ptr;
7949                                 break;
7950                         case P_INTEGER:
7951                         case P_OCTAL:
7952                         case P_ENUM:
7953                                 parm_table[i].def.ivalue =
7954                                         *(int *)parm_table[i].ptr;
7955                                 break;
7956                         case P_SEP:
7957                                 break;
7958                 }
7959         }
7960         defaults_saved = True;
7961 }
7962
7963 /*******************************************************************
7964  Set the server type we will announce as via nmbd.
7965 ********************************************************************/
7966
7967 static const struct srv_role_tab {
7968         uint32 role;
7969         const char *role_str;
7970 } srv_role_tab [] = {
7971         { ROLE_STANDALONE, "ROLE_STANDALONE" },
7972         { ROLE_DOMAIN_MEMBER, "ROLE_DOMAIN_MEMBER" },
7973         { ROLE_DOMAIN_BDC, "ROLE_DOMAIN_BDC" },
7974         { ROLE_DOMAIN_PDC, "ROLE_DOMAIN_PDC" },
7975         { 0, NULL }
7976 };
7977
7978 const char* server_role_str(uint32 role)
7979 {
7980         int i = 0;
7981         for (i=0; srv_role_tab[i].role_str; i++) {
7982                 if (role == srv_role_tab[i].role) {
7983                         return srv_role_tab[i].role_str;
7984                 }
7985         }
7986         return NULL;
7987 }
7988
7989 static void set_server_role(void)
7990 {
7991         server_role = ROLE_STANDALONE;
7992
7993         switch (lp_security()) {
7994                 case SEC_SHARE:
7995                         if (lp_domain_logons())
7996                                 DEBUG(0, ("Server's Role (logon server) conflicts with share-level security\n"));
7997                         break;
7998                 case SEC_SERVER:
7999                         if (lp_domain_logons())
8000                                 DEBUG(0, ("Server's Role (logon server) conflicts with server-level security\n"));
8001                         /* this used to be considered ROLE_DOMAIN_MEMBER but that's just wrong */
8002                         server_role = ROLE_STANDALONE;
8003                         break;
8004                 case SEC_DOMAIN:
8005                         if (lp_domain_logons()) {
8006                                 DEBUG(1, ("Server's Role (logon server) NOT ADVISED with domain-level security\n"));
8007                                 server_role = ROLE_DOMAIN_BDC;
8008                                 break;
8009                         }
8010                         server_role = ROLE_DOMAIN_MEMBER;
8011                         break;
8012                 case SEC_ADS:
8013                         if (lp_domain_logons()) {
8014                                 server_role = ROLE_DOMAIN_PDC;
8015                                 break;
8016                         }
8017                         server_role = ROLE_DOMAIN_MEMBER;
8018                         break;
8019                 case SEC_USER:
8020                         if (lp_domain_logons()) {
8021
8022                                 if (Globals.iDomainMaster) /* auto or yes */ 
8023                                         server_role = ROLE_DOMAIN_PDC;
8024                                 else
8025                                         server_role = ROLE_DOMAIN_BDC;
8026                         }
8027                         break;
8028                 default:
8029                         DEBUG(0, ("Server's Role undefined due to unknown security mode\n"));
8030                         break;
8031         }
8032
8033         DEBUG(10, ("set_server_role: role = %s\n", server_role_str(server_role)));
8034 }
8035
8036 /***********************************************************
8037  If we should send plaintext/LANMAN passwords in the clinet
8038 ************************************************************/
8039
8040 static void set_allowed_client_auth(void)
8041 {
8042         if (Globals.bClientNTLMv2Auth) {
8043                 Globals.bClientLanManAuth = False;
8044         }
8045         if (!Globals.bClientLanManAuth) {
8046                 Globals.bClientPlaintextAuth = False;
8047         }
8048 }
8049
8050 /***************************************************************************
8051  JRA.
8052  The following code allows smbd to read a user defined share file.
8053  Yes, this is my intent. Yes, I'm comfortable with that...
8054
8055  THE FOLLOWING IS SECURITY CRITICAL CODE.
8056
8057  It washes your clothes, it cleans your house, it guards you while you sleep...
8058  Do not f%^k with it....
8059 ***************************************************************************/
8060
8061 #define MAX_USERSHARE_FILE_SIZE (10*1024)
8062
8063 /***************************************************************************
8064  Check allowed stat state of a usershare file.
8065  Ensure we print out who is dicking with us so the admin can
8066  get their sorry ass fired.
8067 ***************************************************************************/
8068
8069 static bool check_usershare_stat(const char *fname, SMB_STRUCT_STAT *psbuf)
8070 {
8071         if (!S_ISREG(psbuf->st_mode)) {
8072                 DEBUG(0,("check_usershare_stat: file %s owned by uid %u is "
8073                         "not a regular file\n",
8074                         fname, (unsigned int)psbuf->st_uid ));
8075                 return False;
8076         }
8077
8078         /* Ensure this doesn't have the other write bit set. */
8079         if (psbuf->st_mode & S_IWOTH) {
8080                 DEBUG(0,("check_usershare_stat: file %s owned by uid %u allows "
8081                         "public write. Refusing to allow as a usershare file.\n",
8082                         fname, (unsigned int)psbuf->st_uid ));
8083                 return False;
8084         }
8085
8086         /* Should be 10k or less. */
8087         if (psbuf->st_size > MAX_USERSHARE_FILE_SIZE) {
8088                 DEBUG(0,("check_usershare_stat: file %s owned by uid %u is "
8089                         "too large (%u) to be a user share file.\n",
8090                         fname, (unsigned int)psbuf->st_uid,
8091                         (unsigned int)psbuf->st_size ));
8092                 return False;
8093         }
8094
8095         return True;
8096 }
8097
8098 /***************************************************************************
8099  Parse the contents of a usershare file.
8100 ***************************************************************************/
8101
8102 enum usershare_err parse_usershare_file(TALLOC_CTX *ctx,
8103                         SMB_STRUCT_STAT *psbuf,
8104                         const char *servicename,
8105                         int snum,
8106                         char **lines,
8107                         int numlines,
8108                         char **pp_sharepath,
8109                         char **pp_comment,
8110                         SEC_DESC **ppsd,
8111                         bool *pallow_guest)
8112 {
8113         const char **prefixallowlist = lp_usershare_prefix_allow_list();
8114         const char **prefixdenylist = lp_usershare_prefix_deny_list();
8115         int us_vers;
8116         SMB_STRUCT_DIR *dp;
8117         SMB_STRUCT_STAT sbuf;
8118         char *sharepath = NULL;
8119         char *comment = NULL;
8120
8121         *pp_sharepath = NULL;
8122         *pp_comment = NULL;
8123
8124         *pallow_guest = False;
8125
8126         if (numlines < 4) {
8127                 return USERSHARE_MALFORMED_FILE;
8128         }
8129
8130         if (strcmp(lines[0], "#VERSION 1") == 0) {
8131                 us_vers = 1;
8132         } else if (strcmp(lines[0], "#VERSION 2") == 0) {
8133                 us_vers = 2;
8134                 if (numlines < 5) {
8135                         return USERSHARE_MALFORMED_FILE;
8136                 }
8137         } else {
8138                 return USERSHARE_BAD_VERSION;
8139         }
8140
8141         if (strncmp(lines[1], "path=", 5) != 0) {
8142                 return USERSHARE_MALFORMED_PATH;
8143         }
8144
8145         sharepath = talloc_strdup(ctx, &lines[1][5]);
8146         if (!sharepath) {
8147                 return USERSHARE_POSIX_ERR;
8148         }
8149         trim_string(sharepath, " ", " ");
8150
8151         if (strncmp(lines[2], "comment=", 8) != 0) {
8152                 return USERSHARE_MALFORMED_COMMENT_DEF;
8153         }
8154
8155         comment = talloc_strdup(ctx, &lines[2][8]);
8156         if (!comment) {
8157                 return USERSHARE_POSIX_ERR;
8158         }
8159         trim_string(comment, " ", " ");
8160         trim_char(comment, '"', '"');
8161
8162         if (strncmp(lines[3], "usershare_acl=", 14) != 0) {
8163                 return USERSHARE_MALFORMED_ACL_DEF;
8164         }
8165
8166         if (!parse_usershare_acl(ctx, &lines[3][14], ppsd)) {
8167                 return USERSHARE_ACL_ERR;
8168         }
8169
8170         if (us_vers == 2) {
8171                 if (strncmp(lines[4], "guest_ok=", 9) != 0) {
8172                         return USERSHARE_MALFORMED_ACL_DEF;
8173                 }
8174                 if (lines[4][9] == 'y') {
8175                         *pallow_guest = True;
8176                 }
8177         }
8178
8179         if (snum != -1 && (strcmp(sharepath, ServicePtrs[snum]->szPath) == 0)) {
8180                 /* Path didn't change, no checks needed. */
8181                 *pp_sharepath = sharepath;
8182                 *pp_comment = comment;
8183                 return USERSHARE_OK;
8184         }
8185
8186         /* The path *must* be absolute. */
8187         if (sharepath[0] != '/') {
8188                 DEBUG(2,("parse_usershare_file: share %s: path %s is not an absolute path.\n",
8189                         servicename, sharepath));
8190                 return USERSHARE_PATH_NOT_ABSOLUTE;
8191         }
8192
8193         /* If there is a usershare prefix deny list ensure one of these paths
8194            doesn't match the start of the user given path. */
8195         if (prefixdenylist) {
8196                 int i;
8197                 for ( i=0; prefixdenylist[i]; i++ ) {
8198                         DEBUG(10,("parse_usershare_file: share %s : checking prefixdenylist[%d]='%s' against %s\n",
8199                                 servicename, i, prefixdenylist[i], sharepath ));
8200                         if (memcmp( sharepath, prefixdenylist[i], strlen(prefixdenylist[i])) == 0) {
8201                                 DEBUG(2,("parse_usershare_file: share %s path %s starts with one of the "
8202                                         "usershare prefix deny list entries.\n",
8203                                         servicename, sharepath));
8204                                 return USERSHARE_PATH_IS_DENIED;
8205                         }
8206                 }
8207         }
8208
8209         /* If there is a usershare prefix allow list ensure one of these paths
8210            does match the start of the user given path. */
8211
8212         if (prefixallowlist) {
8213                 int i;
8214                 for ( i=0; prefixallowlist[i]; i++ ) {
8215                         DEBUG(10,("parse_usershare_file: share %s checking prefixallowlist[%d]='%s' against %s\n",
8216                                 servicename, i, prefixallowlist[i], sharepath ));
8217                         if (memcmp( sharepath, prefixallowlist[i], strlen(prefixallowlist[i])) == 0) {
8218                                 break;
8219                         }
8220                 }
8221                 if (prefixallowlist[i] == NULL) {
8222                         DEBUG(2,("parse_usershare_file: share %s path %s doesn't start with one of the "
8223                                 "usershare prefix allow list entries.\n",
8224                                 servicename, sharepath));
8225                         return USERSHARE_PATH_NOT_ALLOWED;
8226                 }
8227         }
8228
8229         /* Ensure this is pointing to a directory. */
8230         dp = sys_opendir(sharepath);
8231
8232         if (!dp) {
8233                 DEBUG(2,("parse_usershare_file: share %s path %s is not a directory.\n",
8234                         servicename, sharepath));
8235                 return USERSHARE_PATH_NOT_DIRECTORY;
8236         }
8237
8238         /* Ensure the owner of the usershare file has permission to share
8239            this directory. */
8240
8241         if (sys_stat(sharepath, &sbuf) == -1) {
8242                 DEBUG(2,("parse_usershare_file: share %s : stat failed on path %s. %s\n",
8243                         servicename, sharepath, strerror(errno) ));
8244                 sys_closedir(dp);
8245                 return USERSHARE_POSIX_ERR;
8246         }
8247
8248         sys_closedir(dp);
8249
8250         if (!S_ISDIR(sbuf.st_mode)) {
8251                 DEBUG(2,("parse_usershare_file: share %s path %s is not a directory.\n",
8252                         servicename, sharepath ));
8253                 return USERSHARE_PATH_NOT_DIRECTORY;
8254         }
8255
8256         /* Check if sharing is restricted to owner-only. */
8257         /* psbuf is the stat of the usershare definition file,
8258            sbuf is the stat of the target directory to be shared. */
8259
8260         if (lp_usershare_owner_only()) {
8261                 /* root can share anything. */
8262                 if ((psbuf->st_uid != 0) && (sbuf.st_uid != psbuf->st_uid)) {
8263                         return USERSHARE_PATH_NOT_ALLOWED;
8264                 }
8265         }
8266
8267         *pp_sharepath = sharepath;
8268         *pp_comment = comment;
8269         return USERSHARE_OK;
8270 }
8271
8272 /***************************************************************************
8273  Deal with a usershare file.
8274  Returns:
8275         >= 0 - snum
8276         -1 - Bad name, invalid contents.
8277            - service name already existed and not a usershare, problem
8278             with permissions to share directory etc.
8279 ***************************************************************************/
8280
8281 static int process_usershare_file(const char *dir_name, const char *file_name, int snum_template)
8282 {
8283         SMB_STRUCT_STAT sbuf;
8284         SMB_STRUCT_STAT lsbuf;
8285         char *fname = NULL;
8286         char *sharepath = NULL;
8287         char *comment = NULL;
8288         fstring service_name;
8289         char **lines = NULL;
8290         int numlines = 0;
8291         int fd = -1;
8292         int iService = -1;
8293         TALLOC_CTX *ctx = NULL;
8294         SEC_DESC *psd = NULL;
8295         bool guest_ok = False;
8296
8297         /* Ensure share name doesn't contain invalid characters. */
8298         if (!validate_net_name(file_name, INVALID_SHARENAME_CHARS, strlen(file_name))) {
8299                 DEBUG(0,("process_usershare_file: share name %s contains "
8300                         "invalid characters (any of %s)\n",
8301                         file_name, INVALID_SHARENAME_CHARS ));
8302                 return -1;
8303         }
8304
8305         fstrcpy(service_name, file_name);
8306
8307         if (asprintf(&fname, "%s/%s", dir_name, file_name) < 0) {
8308         }
8309
8310         /* Minimize the race condition by doing an lstat before we
8311            open and fstat. Ensure this isn't a symlink link. */
8312
8313         if (sys_lstat(fname, &lsbuf) != 0) {
8314                 DEBUG(0,("process_usershare_file: stat of %s failed. %s\n",
8315                         fname, strerror(errno) ));
8316                 SAFE_FREE(fname);
8317                 return -1;
8318         }
8319
8320         /* This must be a regular file, not a symlink, directory or
8321            other strange filetype. */
8322         if (!check_usershare_stat(fname, &lsbuf)) {
8323                 SAFE_FREE(fname);
8324                 return -1;
8325         }
8326
8327         {
8328                 char *canon_name = canonicalize_servicename(service_name);
8329                 TDB_DATA data = dbwrap_fetch_bystring(
8330                         ServiceHash, canon_name, canon_name);
8331
8332                 iService = -1;
8333
8334                 if ((data.dptr != NULL) && (data.dsize == sizeof(iService))) {
8335                         iService = *(int *)data.dptr;
8336                 }
8337                 TALLOC_FREE(canon_name);
8338         }
8339
8340         if (iService != -1 && ServicePtrs[iService]->usershare_last_mod == lsbuf.st_mtime) {
8341                 /* Nothing changed - Mark valid and return. */
8342                 DEBUG(10,("process_usershare_file: service %s not changed.\n",
8343                         service_name ));
8344                 ServicePtrs[iService]->usershare = USERSHARE_VALID;
8345                 SAFE_FREE(fname);
8346                 return iService;
8347         }
8348
8349         /* Try and open the file read only - no symlinks allowed. */
8350 #ifdef O_NOFOLLOW
8351         fd = sys_open(fname, O_RDONLY|O_NOFOLLOW, 0);
8352 #else
8353         fd = sys_open(fname, O_RDONLY, 0);
8354 #endif
8355
8356         if (fd == -1) {
8357                 DEBUG(0,("process_usershare_file: unable to open %s. %s\n",
8358                         fname, strerror(errno) ));
8359                 SAFE_FREE(fname);
8360                 return -1;
8361         }
8362
8363         /* Now fstat to be *SURE* it's a regular file. */
8364         if (sys_fstat(fd, &sbuf) != 0) {
8365                 close(fd);
8366                 DEBUG(0,("process_usershare_file: fstat of %s failed. %s\n",
8367                         fname, strerror(errno) ));
8368                 SAFE_FREE(fname);
8369                 return -1;
8370         }
8371
8372         /* Is it the same dev/inode as was lstated ? */
8373         if (lsbuf.st_dev != sbuf.st_dev || lsbuf.st_ino != sbuf.st_ino) {
8374                 close(fd);
8375                 DEBUG(0,("process_usershare_file: fstat of %s is a different file from lstat. "
8376                         "Symlink spoofing going on ?\n", fname ));
8377                 SAFE_FREE(fname);
8378                 return -1;
8379         }
8380
8381         /* This must be a regular file, not a symlink, directory or
8382            other strange filetype. */
8383         if (!check_usershare_stat(fname, &sbuf)) {
8384                 SAFE_FREE(fname);
8385                 return -1;
8386         }
8387
8388         lines = fd_lines_load(fd, &numlines, MAX_USERSHARE_FILE_SIZE, NULL);
8389
8390         close(fd);
8391         if (lines == NULL) {
8392                 DEBUG(0,("process_usershare_file: loading file %s owned by %u failed.\n",
8393                         fname, (unsigned int)sbuf.st_uid ));
8394                 SAFE_FREE(fname);
8395                 return -1;
8396         }
8397
8398         SAFE_FREE(fname);
8399
8400         /* Should we allow printers to be shared... ? */
8401         ctx = talloc_init("usershare_sd_xctx");
8402         if (!ctx) {
8403                 TALLOC_FREE(lines);
8404                 return 1;
8405         }
8406
8407         if (parse_usershare_file(ctx, &sbuf, service_name,
8408                         iService, lines, numlines, &sharepath,
8409                         &comment, &psd, &guest_ok) != USERSHARE_OK) {
8410                 talloc_destroy(ctx);
8411                 TALLOC_FREE(lines);
8412                 return -1;
8413         }
8414
8415         TALLOC_FREE(lines);
8416
8417         /* Everything ok - add the service possibly using a template. */
8418         if (iService < 0) {
8419                 const struct service *sp = &sDefault;
8420                 if (snum_template != -1) {
8421                         sp = ServicePtrs[snum_template];
8422                 }
8423
8424                 if ((iService = add_a_service(sp, service_name)) < 0) {
8425                         DEBUG(0, ("process_usershare_file: Failed to add "
8426                                 "new service %s\n", service_name));
8427                         talloc_destroy(ctx);
8428                         return -1;
8429                 }
8430
8431                 /* Read only is controlled by usershare ACL below. */
8432                 ServicePtrs[iService]->bRead_only = False;
8433         }
8434
8435         /* Write the ACL of the new/modified share. */
8436         if (!set_share_security(service_name, psd)) {
8437                  DEBUG(0, ("process_usershare_file: Failed to set share "
8438                         "security for user share %s\n",
8439                         service_name ));
8440                 lp_remove_service(iService);
8441                 talloc_destroy(ctx);
8442                 return -1;
8443         }
8444
8445         /* If from a template it may be marked invalid. */
8446         ServicePtrs[iService]->valid = True;
8447
8448         /* Set the service as a valid usershare. */
8449         ServicePtrs[iService]->usershare = USERSHARE_VALID;
8450
8451         /* Set guest access. */
8452         if (lp_usershare_allow_guests()) {
8453                 ServicePtrs[iService]->bGuest_ok = guest_ok;
8454         }
8455
8456         /* And note when it was loaded. */
8457         ServicePtrs[iService]->usershare_last_mod = sbuf.st_mtime;
8458         string_set(&ServicePtrs[iService]->szPath, sharepath);
8459         string_set(&ServicePtrs[iService]->comment, comment);
8460
8461         talloc_destroy(ctx);
8462
8463         return iService;
8464 }
8465
8466 /***************************************************************************
8467  Checks if a usershare entry has been modified since last load.
8468 ***************************************************************************/
8469
8470 static bool usershare_exists(int iService, time_t *last_mod)
8471 {
8472         SMB_STRUCT_STAT lsbuf;
8473         const char *usersharepath = Globals.szUsersharePath;
8474         char *fname;
8475
8476         if (asprintf(&fname, "%s/%s",
8477                                 usersharepath,
8478                                 ServicePtrs[iService]->szService) < 0) {
8479                 return false;
8480         }
8481
8482         if (sys_lstat(fname, &lsbuf) != 0) {
8483                 SAFE_FREE(fname);
8484                 return false;
8485         }
8486
8487         if (!S_ISREG(lsbuf.st_mode)) {
8488                 SAFE_FREE(fname);
8489                 return false;
8490         }
8491
8492         SAFE_FREE(fname);
8493         *last_mod = lsbuf.st_mtime;
8494         return true;
8495 }
8496
8497 /***************************************************************************
8498  Load a usershare service by name. Returns a valid servicenumber or -1.
8499 ***************************************************************************/
8500
8501 int load_usershare_service(const char *servicename)
8502 {
8503         SMB_STRUCT_STAT sbuf;
8504         const char *usersharepath = Globals.szUsersharePath;
8505         int max_user_shares = Globals.iUsershareMaxShares;
8506         int snum_template = -1;
8507
8508         if (*usersharepath == 0 ||  max_user_shares == 0) {
8509                 return -1;
8510         }
8511
8512         if (sys_stat(usersharepath, &sbuf) != 0) {
8513                 DEBUG(0,("load_usershare_service: stat of %s failed. %s\n",
8514                         usersharepath, strerror(errno) ));
8515                 return -1;
8516         }
8517
8518         if (!S_ISDIR(sbuf.st_mode)) {
8519                 DEBUG(0,("load_usershare_service: %s is not a directory.\n",
8520                         usersharepath ));
8521                 return -1;
8522         }
8523
8524         /*
8525          * This directory must be owned by root, and have the 't' bit set.
8526          * It also must not be writable by "other".
8527          */
8528
8529 #ifdef S_ISVTX
8530         if (sbuf.st_uid != 0 || !(sbuf.st_mode & S_ISVTX) || (sbuf.st_mode & S_IWOTH)) {
8531 #else
8532         if (sbuf.st_uid != 0 || (sbuf.st_mode & S_IWOTH)) {
8533 #endif
8534                 DEBUG(0,("load_usershare_service: directory %s is not owned by root "
8535                         "or does not have the sticky bit 't' set or is writable by anyone.\n",
8536                         usersharepath ));
8537                 return -1;
8538         }
8539
8540         /* Ensure the template share exists if it's set. */
8541         if (Globals.szUsershareTemplateShare[0]) {
8542                 /* We can't use lp_servicenumber here as we are recommending that
8543                    template shares have -valid=False set. */
8544                 for (snum_template = iNumServices - 1; snum_template >= 0; snum_template--) {
8545                         if (ServicePtrs[snum_template]->szService &&
8546                                         strequal(ServicePtrs[snum_template]->szService,
8547                                                 Globals.szUsershareTemplateShare)) {
8548                                 break;
8549                         }
8550                 }
8551
8552                 if (snum_template == -1) {
8553                         DEBUG(0,("load_usershare_service: usershare template share %s "
8554                                 "does not exist.\n",
8555                                 Globals.szUsershareTemplateShare ));
8556                         return -1;
8557                 }
8558         }
8559
8560         return process_usershare_file(usersharepath, servicename, snum_template);
8561 }
8562
8563 /***************************************************************************
8564  Load all user defined shares from the user share directory.
8565  We only do this if we're enumerating the share list.
8566  This is the function that can delete usershares that have
8567  been removed.
8568 ***************************************************************************/
8569
8570 int load_usershare_shares(void)
8571 {
8572         SMB_STRUCT_DIR *dp;
8573         SMB_STRUCT_STAT sbuf;
8574         SMB_STRUCT_DIRENT *de;
8575         int num_usershares = 0;
8576         int max_user_shares = Globals.iUsershareMaxShares;
8577         unsigned int num_dir_entries, num_bad_dir_entries, num_tmp_dir_entries;
8578         unsigned int allowed_bad_entries = ((2*max_user_shares)/10);
8579         unsigned int allowed_tmp_entries = ((2*max_user_shares)/10);
8580         int iService;
8581         int snum_template = -1;
8582         const char *usersharepath = Globals.szUsersharePath;
8583         int ret = lp_numservices();
8584
8585         if (max_user_shares == 0 || *usersharepath == '\0') {
8586                 return lp_numservices();
8587         }
8588
8589         if (sys_stat(usersharepath, &sbuf) != 0) {
8590                 DEBUG(0,("load_usershare_shares: stat of %s failed. %s\n",
8591                         usersharepath, strerror(errno) ));
8592                 return ret;
8593         }
8594
8595         /*
8596          * This directory must be owned by root, and have the 't' bit set.
8597          * It also must not be writable by "other".
8598          */
8599
8600 #ifdef S_ISVTX
8601         if (sbuf.st_uid != 0 || !(sbuf.st_mode & S_ISVTX) || (sbuf.st_mode & S_IWOTH)) {
8602 #else
8603         if (sbuf.st_uid != 0 || (sbuf.st_mode & S_IWOTH)) {
8604 #endif
8605                 DEBUG(0,("load_usershare_shares: directory %s is not owned by root "
8606                         "or does not have the sticky bit 't' set or is writable by anyone.\n",
8607                         usersharepath ));
8608                 return ret;
8609         }
8610
8611         /* Ensure the template share exists if it's set. */
8612         if (Globals.szUsershareTemplateShare[0]) {
8613                 /* We can't use lp_servicenumber here as we are recommending that
8614                    template shares have -valid=False set. */
8615                 for (snum_template = iNumServices - 1; snum_template >= 0; snum_template--) {
8616                         if (ServicePtrs[snum_template]->szService &&
8617                                         strequal(ServicePtrs[snum_template]->szService,
8618                                                 Globals.szUsershareTemplateShare)) {
8619                                 break;
8620                         }
8621                 }
8622
8623                 if (snum_template == -1) {
8624                         DEBUG(0,("load_usershare_shares: usershare template share %s "
8625                                 "does not exist.\n",
8626                                 Globals.szUsershareTemplateShare ));
8627                         return ret;
8628                 }
8629         }
8630
8631         /* Mark all existing usershares as pending delete. */
8632         for (iService = iNumServices - 1; iService >= 0; iService--) {
8633                 if (VALID(iService) && ServicePtrs[iService]->usershare) {
8634                         ServicePtrs[iService]->usershare = USERSHARE_PENDING_DELETE;
8635                 }
8636         }
8637
8638         dp = sys_opendir(usersharepath);
8639         if (!dp) {
8640                 DEBUG(0,("load_usershare_shares:: failed to open directory %s. %s\n",
8641                         usersharepath, strerror(errno) ));
8642                 return ret;
8643         }
8644
8645         for (num_dir_entries = 0, num_bad_dir_entries = 0, num_tmp_dir_entries = 0;
8646                         (de = sys_readdir(dp));
8647                         num_dir_entries++ ) {
8648                 int r;
8649                 const char *n = de->d_name;
8650
8651                 /* Ignore . and .. */
8652                 if (*n == '.') {
8653                         if ((n[1] == '\0') || (n[1] == '.' && n[2] == '\0')) {
8654                                 continue;
8655                         }
8656                 }
8657
8658                 if (n[0] == ':') {
8659                         /* Temporary file used when creating a share. */
8660                         num_tmp_dir_entries++;
8661                 }
8662
8663                 /* Allow 20% tmp entries. */
8664                 if (num_tmp_dir_entries > allowed_tmp_entries) {
8665                         DEBUG(0,("load_usershare_shares: too many temp entries (%u) "
8666                                 "in directory %s\n",
8667                                 num_tmp_dir_entries, usersharepath));
8668                         break;
8669                 }
8670
8671                 r = process_usershare_file(usersharepath, n, snum_template);
8672                 if (r == 0) {
8673                         /* Update the services count. */
8674                         num_usershares++;
8675                         if (num_usershares >= max_user_shares) {
8676                                 DEBUG(0,("load_usershare_shares: max user shares reached "
8677                                         "on file %s in directory %s\n",
8678                                         n, usersharepath ));
8679                                 break;
8680                         }
8681                 } else if (r == -1) {
8682                         num_bad_dir_entries++;
8683                 }
8684
8685                 /* Allow 20% bad entries. */
8686                 if (num_bad_dir_entries > allowed_bad_entries) {
8687                         DEBUG(0,("load_usershare_shares: too many bad entries (%u) "
8688                                 "in directory %s\n",
8689                                 num_bad_dir_entries, usersharepath));
8690                         break;
8691                 }
8692
8693                 /* Allow 20% bad entries. */
8694                 if (num_dir_entries > max_user_shares + allowed_bad_entries) {
8695                         DEBUG(0,("load_usershare_shares: too many total entries (%u) "
8696                         "in directory %s\n",
8697                         num_dir_entries, usersharepath));
8698                         break;
8699                 }
8700         }
8701
8702         sys_closedir(dp);
8703
8704         /* Sweep through and delete any non-refreshed usershares that are
8705            not currently in use. */
8706         for (iService = iNumServices - 1; iService >= 0; iService--) {
8707                 if (VALID(iService) && (ServicePtrs[iService]->usershare == USERSHARE_PENDING_DELETE)) {
8708                         if (conn_snum_used(iService)) {
8709                                 continue;
8710                         }
8711                         /* Remove from the share ACL db. */
8712                         DEBUG(10,("load_usershare_shares: Removing deleted usershare %s\n",
8713                                 lp_servicename(iService) ));
8714                         delete_share_security(lp_servicename(iService));
8715                         free_service_byindex(iService);
8716                 }
8717         }
8718
8719         return lp_numservices();
8720 }
8721
8722 /********************************************************
8723  Destroy global resources allocated in this file
8724 ********************************************************/
8725
8726 void gfree_loadparm(void)
8727 {
8728         struct file_lists *f;
8729         struct file_lists *next;
8730         int i;
8731
8732         /* Free the file lists */
8733
8734         f = file_lists;
8735         while( f ) {
8736                 next = f->next;
8737                 SAFE_FREE( f->name );
8738                 SAFE_FREE( f->subfname );
8739                 SAFE_FREE( f );
8740                 f = next;
8741         }
8742         file_lists = NULL;
8743
8744         /* Free resources allocated to services */
8745
8746         for ( i = 0; i < iNumServices; i++ ) {
8747                 if ( VALID(i) ) {
8748                         free_service_byindex(i);
8749                 }
8750         }
8751
8752         SAFE_FREE( ServicePtrs );
8753         iNumServices = 0;
8754
8755         /* Now release all resources allocated to global
8756            parameters and the default service */
8757
8758         free_global_parameters();
8759 }
8760
8761
8762 /***************************************************************************
8763  Allow client apps to specify that they are a client
8764 ***************************************************************************/
8765 void lp_set_in_client(bool b)
8766 {
8767     in_client = b;
8768 }
8769
8770
8771 /***************************************************************************
8772  Determine if we're running in a client app
8773 ***************************************************************************/
8774 bool lp_is_in_client(void)
8775 {
8776     return in_client;
8777 }
8778
8779 /***************************************************************************
8780  Load the services array from the services file. Return True on success, 
8781  False on failure.
8782 ***************************************************************************/
8783
8784 bool lp_load_ex(const char *pszFname,
8785                 bool global_only,
8786                 bool save_defaults,
8787                 bool add_ipc,
8788                 bool initialize_globals,
8789                 bool allow_include_registry,
8790                 bool allow_registry_shares)
8791 {
8792         char *n2 = NULL;
8793         bool bRetval;
8794
8795         bRetval = False;
8796
8797         DEBUG(3, ("lp_load_ex: refreshing parameters\n"));
8798
8799         bInGlobalSection = True;
8800         bGlobalOnly = global_only;
8801         bAllowIncludeRegistry = allow_include_registry;
8802
8803         init_globals(! initialize_globals);
8804         debug_init();
8805
8806         if (save_defaults) {
8807                 init_locals();
8808                 lp_save_defaults();
8809         }
8810
8811         free_param_opts(&Globals.param_opt);
8812
8813         /* We get sections first, so have to start 'behind' to make up */
8814         iServiceIndex = -1;
8815
8816         if (lp_config_backend_is_file()) {
8817                 n2 = alloc_sub_basic(get_current_username(),
8818                                         current_user_info.domain,
8819                                         pszFname);
8820                 if (!n2) {
8821                         smb_panic("lp_load_ex: out of memory");
8822                 }
8823
8824                 add_to_file_list(pszFname, n2);
8825
8826                 bRetval = pm_process(n2, do_section, do_parameter, NULL);
8827                 SAFE_FREE(n2);
8828
8829                 /* finish up the last section */
8830                 DEBUG(4, ("pm_process() returned %s\n", BOOLSTR(bRetval)));
8831                 if (bRetval) {
8832                         if (iServiceIndex >= 0) {
8833                                 bRetval = service_ok(iServiceIndex);
8834                         }
8835                 }
8836
8837                 if (lp_config_backend_is_registry()) {
8838                         /* config backend changed to registry in config file */
8839                         /*
8840                          * We need to use this extra global variable here to
8841                          * survive restart: init_globals uses this as a default
8842                          * for ConfigBackend. Otherwise, init_globals would
8843                          *  send us into an endless loop here.
8844                          */
8845                         config_backend = CONFIG_BACKEND_REGISTRY;
8846                         /* start over */
8847                         DEBUG(1, ("lp_load_ex: changing to config backend "
8848                                   "registry\n"));
8849                         init_globals(false);
8850                         lp_kill_all_services();
8851                         return lp_load_ex(pszFname, global_only, save_defaults,
8852                                           add_ipc, initialize_globals,
8853                                           allow_include_registry,
8854                                           allow_registry_shares);
8855                 }
8856         } else if (lp_config_backend_is_registry()) {
8857                 bRetval = process_registry_globals();
8858         } else {
8859                 DEBUG(0, ("Illegal config  backend given: %d\n",
8860                           lp_config_backend()));
8861                 bRetval = false;
8862         }
8863
8864         if (bRetval && lp_registry_shares() && allow_registry_shares) {
8865                 bRetval = process_registry_shares();
8866         }
8867
8868         lp_add_auto_services(lp_auto_services());
8869
8870         if (add_ipc) {
8871                 /* When 'restrict anonymous = 2' guest connections to ipc$
8872                    are denied */
8873                 lp_add_ipc("IPC$", (lp_restrict_anonymous() < 2));
8874                 if ( lp_enable_asu_support() ) {
8875                         lp_add_ipc("ADMIN$", false);
8876                 }
8877         }
8878
8879         set_server_role();
8880         set_default_server_announce_type();
8881         set_allowed_client_auth();
8882
8883         bLoaded = True;
8884
8885         /* Now we check bWINSsupport and set szWINSserver to 127.0.0.1 */
8886         /* if bWINSsupport is true and we are in the client            */
8887         if (lp_is_in_client() && Globals.bWINSsupport) {
8888                 lp_do_parameter(GLOBAL_SECTION_SNUM, "wins server", "127.0.0.1");
8889         }
8890
8891         init_iconv();
8892
8893         bAllowIncludeRegistry = true;
8894
8895         return (bRetval);
8896 }
8897
8898 bool lp_load(const char *pszFname,
8899              bool global_only,
8900              bool save_defaults,
8901              bool add_ipc,
8902              bool initialize_globals)
8903 {
8904         return lp_load_ex(pszFname,
8905                           global_only,
8906                           save_defaults,
8907                           add_ipc,
8908                           initialize_globals,
8909                           true, false);
8910 }
8911
8912 bool lp_load_initial_only(const char *pszFname)
8913 {
8914         return lp_load_ex(pszFname,
8915                           true,
8916                           false,
8917                           false,
8918                           true,
8919                           false,
8920                           false);
8921 }
8922
8923 bool lp_load_with_registry_shares(const char *pszFname,
8924                                   bool global_only,
8925                                   bool save_defaults,
8926                                   bool add_ipc,
8927                                   bool initialize_globals)
8928 {
8929         return lp_load_ex(pszFname,
8930                           global_only,
8931                           save_defaults,
8932                           add_ipc,
8933                           initialize_globals,
8934                           true,
8935                           true);
8936 }
8937
8938 /***************************************************************************
8939  Return the max number of services.
8940 ***************************************************************************/
8941
8942 int lp_numservices(void)
8943 {
8944         return (iNumServices);
8945 }
8946
8947 /***************************************************************************
8948 Display the contents of the services array in human-readable form.
8949 ***************************************************************************/
8950
8951 void lp_dump(FILE *f, bool show_defaults, int maxtoprint)
8952 {
8953         int iService;
8954
8955         if (show_defaults)
8956                 defaults_saved = False;
8957
8958         dump_globals(f);
8959
8960         dump_a_service(&sDefault, f);
8961
8962         for (iService = 0; iService < maxtoprint; iService++) {
8963                 fprintf(f,"\n");
8964                 lp_dump_one(f, show_defaults, iService);
8965         }
8966 }
8967
8968 /***************************************************************************
8969 Display the contents of one service in human-readable form.
8970 ***************************************************************************/
8971
8972 void lp_dump_one(FILE * f, bool show_defaults, int snum)
8973 {
8974         if (VALID(snum)) {
8975                 if (ServicePtrs[snum]->szService[0] == '\0')
8976                         return;
8977                 dump_a_service(ServicePtrs[snum], f);
8978         }
8979 }
8980
8981 /***************************************************************************
8982 Return the number of the service with the given name, or -1 if it doesn't
8983 exist. Note that this is a DIFFERENT ANIMAL from the internal function
8984 getservicebyname()! This works ONLY if all services have been loaded, and
8985 does not copy the found service.
8986 ***************************************************************************/
8987
8988 int lp_servicenumber(const char *pszServiceName)
8989 {
8990         int iService;
8991         fstring serviceName;
8992         
8993         if (!pszServiceName) {
8994                 return GLOBAL_SECTION_SNUM;
8995         }
8996         
8997         for (iService = iNumServices - 1; iService >= 0; iService--) {
8998                 if (VALID(iService) && ServicePtrs[iService]->szService) {
8999                         /*
9000                          * The substitution here is used to support %U is
9001                          * service names
9002                          */
9003                         fstrcpy(serviceName, ServicePtrs[iService]->szService);
9004                         standard_sub_basic(get_current_username(),
9005                                            current_user_info.domain,
9006                                            serviceName,sizeof(serviceName));
9007                         if (strequal(serviceName, pszServiceName)) {
9008                                 break;
9009                         }
9010                 }
9011         }
9012
9013         if (iService >= 0 && ServicePtrs[iService]->usershare == USERSHARE_VALID) {
9014                 time_t last_mod;
9015
9016                 if (!usershare_exists(iService, &last_mod)) {
9017                         /* Remove the share security tdb entry for it. */
9018                         delete_share_security(lp_servicename(iService));
9019                         /* Remove it from the array. */
9020                         free_service_byindex(iService);
9021                         /* Doesn't exist anymore. */
9022                         return GLOBAL_SECTION_SNUM;
9023                 }
9024
9025                 /* Has it been modified ? If so delete and reload. */
9026                 if (ServicePtrs[iService]->usershare_last_mod < last_mod) {
9027                         /* Remove it from the array. */
9028                         free_service_byindex(iService);
9029                         /* and now reload it. */
9030                         iService = load_usershare_service(pszServiceName);
9031                 }
9032         }
9033
9034         if (iService < 0) {
9035                 DEBUG(7,("lp_servicenumber: couldn't find %s\n", pszServiceName));
9036                 return GLOBAL_SECTION_SNUM;
9037         }
9038
9039         return (iService);
9040 }
9041
9042 bool share_defined(const char *service_name)
9043 {
9044         return (lp_servicenumber(service_name) != -1);
9045 }
9046
9047 struct share_params *get_share_params(TALLOC_CTX *mem_ctx,
9048                                       const char *sharename)
9049 {
9050         struct share_params *result;
9051         char *sname;
9052         int snum;
9053
9054         if (!(sname = SMB_STRDUP(sharename))) {
9055                 return NULL;
9056         }
9057
9058         snum = find_service(sname);
9059         SAFE_FREE(sname);
9060
9061         if (snum < 0) {
9062                 return NULL;
9063         }
9064
9065         if (!(result = TALLOC_P(mem_ctx, struct share_params))) {
9066                 DEBUG(0, ("talloc failed\n"));
9067                 return NULL;
9068         }
9069
9070         result->service = snum;
9071         return result;
9072 }
9073
9074 struct share_iterator *share_list_all(TALLOC_CTX *mem_ctx)
9075 {
9076         struct share_iterator *result;
9077
9078         if (!(result = TALLOC_P(mem_ctx, struct share_iterator))) {
9079                 DEBUG(0, ("talloc failed\n"));
9080                 return NULL;
9081         }
9082
9083         result->next_id = 0;
9084         return result;
9085 }
9086
9087 struct share_params *next_share(struct share_iterator *list)
9088 {
9089         struct share_params *result;
9090
9091         while (!lp_snum_ok(list->next_id) &&
9092                (list->next_id < lp_numservices())) {
9093                 list->next_id += 1;
9094         }
9095
9096         if (list->next_id >= lp_numservices()) {
9097                 return NULL;
9098         }
9099
9100         if (!(result = TALLOC_P(list, struct share_params))) {
9101                 DEBUG(0, ("talloc failed\n"));
9102                 return NULL;
9103         }
9104
9105         result->service = list->next_id;
9106         list->next_id += 1;
9107         return result;
9108 }
9109
9110 struct share_params *next_printer(struct share_iterator *list)
9111 {
9112         struct share_params *result;
9113
9114         while ((result = next_share(list)) != NULL) {
9115                 if (lp_print_ok(result->service)) {
9116                         break;
9117                 }
9118         }
9119         return result;
9120 }
9121
9122 /*
9123  * This is a hack for a transition period until we transformed all code from
9124  * service numbers to struct share_params.
9125  */
9126
9127 struct share_params *snum2params_static(int snum)
9128 {
9129         static struct share_params result;
9130         result.service = snum;
9131         return &result;
9132 }
9133
9134 /*******************************************************************
9135  A useful volume label function. 
9136 ********************************************************************/
9137
9138 const char *volume_label(int snum)
9139 {
9140         char *ret;
9141         const char *label = lp_volume(snum);
9142         if (!*label) {
9143                 label = lp_servicename(snum);
9144         }
9145                 
9146         /* This returns a 33 byte guarenteed null terminated string. */
9147         ret = talloc_strndup(talloc_tos(), label, 32);
9148         if (!ret) {
9149                 return "";
9150         }               
9151         return ret;
9152 }
9153
9154 /*******************************************************************
9155  Set the server type we will announce as via nmbd.
9156 ********************************************************************/
9157
9158 static void set_default_server_announce_type(void)
9159 {
9160         default_server_announce = 0;
9161         default_server_announce |= SV_TYPE_WORKSTATION;
9162         default_server_announce |= SV_TYPE_SERVER;
9163         default_server_announce |= SV_TYPE_SERVER_UNIX;
9164
9165         /* note that the flag should be set only if we have a 
9166            printer service but nmbd doesn't actually load the 
9167            services so we can't tell   --jerry */
9168
9169         default_server_announce |= SV_TYPE_PRINTQ_SERVER;
9170
9171         switch (lp_announce_as()) {
9172                 case ANNOUNCE_AS_NT_SERVER:
9173                         default_server_announce |= SV_TYPE_SERVER_NT;
9174                         /* fall through... */
9175                 case ANNOUNCE_AS_NT_WORKSTATION:
9176                         default_server_announce |= SV_TYPE_NT;
9177                         break;
9178                 case ANNOUNCE_AS_WIN95:
9179                         default_server_announce |= SV_TYPE_WIN95_PLUS;
9180                         break;
9181                 case ANNOUNCE_AS_WFW:
9182                         default_server_announce |= SV_TYPE_WFW;
9183                         break;
9184                 default:
9185                         break;
9186         }
9187
9188         switch (lp_server_role()) {
9189                 case ROLE_DOMAIN_MEMBER:
9190                         default_server_announce |= SV_TYPE_DOMAIN_MEMBER;
9191                         break;
9192                 case ROLE_DOMAIN_PDC:
9193                         default_server_announce |= SV_TYPE_DOMAIN_CTRL;
9194                         break;
9195                 case ROLE_DOMAIN_BDC:
9196                         default_server_announce |= SV_TYPE_DOMAIN_BAKCTRL;
9197                         break;
9198                 case ROLE_STANDALONE:
9199                 default:
9200                         break;
9201         }
9202         if (lp_time_server())
9203                 default_server_announce |= SV_TYPE_TIME_SOURCE;
9204
9205         if (lp_host_msdfs())
9206                 default_server_announce |= SV_TYPE_DFS_SERVER;
9207 }
9208
9209 /***********************************************************
9210  returns role of Samba server
9211 ************************************************************/
9212
9213 int lp_server_role(void)
9214 {
9215         return server_role;
9216 }
9217
9218 /***********************************************************
9219  If we are PDC then prefer us as DMB
9220 ************************************************************/
9221
9222 bool lp_domain_master(void)
9223 {
9224         if (Globals.iDomainMaster == Auto)
9225                 return (lp_server_role() == ROLE_DOMAIN_PDC);
9226
9227         return (bool)Globals.iDomainMaster;
9228 }
9229
9230 /***********************************************************
9231  If we are DMB then prefer us as LMB
9232 ************************************************************/
9233
9234 bool lp_preferred_master(void)
9235 {
9236         if (Globals.iPreferredMaster == Auto)
9237                 return (lp_local_master() && lp_domain_master());
9238
9239         return (bool)Globals.iPreferredMaster;
9240 }
9241
9242 /*******************************************************************
9243  Remove a service.
9244 ********************************************************************/
9245
9246 void lp_remove_service(int snum)
9247 {
9248         ServicePtrs[snum]->valid = False;
9249         invalid_services[num_invalid_services++] = snum;
9250 }
9251
9252 /*******************************************************************
9253  Copy a service.
9254 ********************************************************************/
9255
9256 void lp_copy_service(int snum, const char *new_name)
9257 {
9258         do_section(new_name, NULL);
9259         if (snum >= 0) {
9260                 snum = lp_servicenumber(new_name);
9261                 if (snum >= 0)
9262                         lp_do_parameter(snum, "copy", lp_servicename(snum));
9263         }
9264 }
9265
9266
9267 /*******************************************************************
9268  Get the default server type we will announce as via nmbd.
9269 ********************************************************************/
9270
9271 int lp_default_server_announce(void)
9272 {
9273         return default_server_announce;
9274 }
9275
9276 /*******************************************************************
9277  Split the announce version into major and minor numbers.
9278 ********************************************************************/
9279
9280 int lp_major_announce_version(void)
9281 {
9282         static bool got_major = False;
9283         static int major_version = DEFAULT_MAJOR_VERSION;
9284         char *vers;
9285         char *p;
9286
9287         if (got_major)
9288                 return major_version;
9289
9290         got_major = True;
9291         if ((vers = lp_announce_version()) == NULL)
9292                 return major_version;
9293
9294         if ((p = strchr_m(vers, '.')) == 0)
9295                 return major_version;
9296
9297         *p = '\0';
9298         major_version = atoi(vers);
9299         return major_version;
9300 }
9301
9302 int lp_minor_announce_version(void)
9303 {
9304         static bool got_minor = False;
9305         static int minor_version = DEFAULT_MINOR_VERSION;
9306         char *vers;
9307         char *p;
9308
9309         if (got_minor)
9310                 return minor_version;
9311
9312         got_minor = True;
9313         if ((vers = lp_announce_version()) == NULL)
9314                 return minor_version;
9315
9316         if ((p = strchr_m(vers, '.')) == 0)
9317                 return minor_version;
9318
9319         p++;
9320         minor_version = atoi(p);
9321         return minor_version;
9322 }
9323
9324 /***********************************************************
9325  Set the global name resolution order (used in smbclient).
9326 ************************************************************/
9327
9328 void lp_set_name_resolve_order(const char *new_order)
9329 {
9330         string_set(&Globals.szNameResolveOrder, new_order);
9331 }
9332
9333 const char *lp_printername(int snum)
9334 {
9335         const char *ret = _lp_printername(snum);
9336         if (ret == NULL || (ret != NULL && *ret == '\0'))
9337                 ret = lp_const_servicename(snum);
9338
9339         return ret;
9340 }
9341
9342
9343 /***********************************************************
9344  Allow daemons such as winbindd to fix their logfile name.
9345 ************************************************************/
9346
9347 void lp_set_logfile(const char *name)
9348 {
9349         string_set(&Globals.szLogFile, name);
9350         debug_set_logfile(name);
9351 }
9352
9353 /*******************************************************************
9354  Return the max print jobs per queue.
9355 ********************************************************************/
9356
9357 int lp_maxprintjobs(int snum)
9358 {
9359         int maxjobs = LP_SNUM_OK(snum) ? ServicePtrs[snum]->iMaxPrintJobs : sDefault.iMaxPrintJobs;
9360         if (maxjobs <= 0 || maxjobs >= PRINT_MAX_JOBID)
9361                 maxjobs = PRINT_MAX_JOBID - 1;
9362
9363         return maxjobs;
9364 }
9365
9366 const char *lp_printcapname(void)
9367 {
9368         if ((Globals.szPrintcapname != NULL) &&
9369             (Globals.szPrintcapname[0] != '\0'))
9370                 return Globals.szPrintcapname;
9371
9372         if (sDefault.iPrinting == PRINT_CUPS) {
9373 #ifdef HAVE_CUPS
9374                 return "cups";
9375 #else
9376                 return "lpstat";
9377 #endif
9378         }
9379
9380         if (sDefault.iPrinting == PRINT_BSD)
9381                 return "/etc/printcap";
9382
9383         return PRINTCAP_NAME;
9384 }
9385
9386 /*******************************************************************
9387  Ensure we don't use sendfile if server smb signing is active.
9388 ********************************************************************/
9389
9390 static uint32 spoolss_state;
9391
9392 bool lp_disable_spoolss( void )
9393 {
9394         if ( spoolss_state == SVCCTL_STATE_UNKNOWN )
9395                 spoolss_state = _lp_disable_spoolss() ? SVCCTL_STOPPED : SVCCTL_RUNNING;
9396
9397         return spoolss_state == SVCCTL_STOPPED ? True : False;
9398 }
9399
9400 void lp_set_spoolss_state( uint32 state )
9401 {
9402         SMB_ASSERT( (state == SVCCTL_STOPPED) || (state == SVCCTL_RUNNING) );
9403
9404         spoolss_state = state;
9405 }
9406
9407 uint32 lp_get_spoolss_state( void )
9408 {
9409         return lp_disable_spoolss() ? SVCCTL_STOPPED : SVCCTL_RUNNING;
9410 }
9411
9412 /*******************************************************************
9413  Ensure we don't use sendfile if server smb signing is active.
9414 ********************************************************************/
9415
9416 bool lp_use_sendfile(int snum)
9417 {
9418         /* Using sendfile blows the brains out of any DOS or Win9x TCP stack... JRA. */
9419         if (Protocol < PROTOCOL_NT1) {
9420                 return False;
9421         }
9422         return (_lp_use_sendfile(snum) &&
9423                         (get_remote_arch() != RA_WIN95) &&
9424                         !srv_is_signing_active());
9425 }
9426
9427 /*******************************************************************
9428  Turn off sendfile if we find the underlying OS doesn't support it.
9429 ********************************************************************/
9430
9431 void set_use_sendfile(int snum, bool val)
9432 {
9433         if (LP_SNUM_OK(snum))
9434                 ServicePtrs[snum]->bUseSendfile = val;
9435         else
9436                 sDefault.bUseSendfile = val;
9437 }
9438
9439 /*******************************************************************
9440  Turn off storing DOS attributes if this share doesn't support it.
9441 ********************************************************************/
9442
9443 void set_store_dos_attributes(int snum, bool val)
9444 {
9445         if (!LP_SNUM_OK(snum))
9446                 return;
9447         ServicePtrs[(snum)]->bStoreDosAttributes = val;
9448 }
9449
9450 void lp_set_mangling_method(const char *new_method)
9451 {
9452         string_set(&Globals.szManglingMethod, new_method);
9453 }
9454
9455 /*******************************************************************
9456  Global state for POSIX pathname processing.
9457 ********************************************************************/
9458
9459 static bool posix_pathnames;
9460
9461 bool lp_posix_pathnames(void)
9462 {
9463         return posix_pathnames;
9464 }
9465
9466 /*******************************************************************
9467  Change everything needed to ensure POSIX pathname processing (currently
9468  not much).
9469 ********************************************************************/
9470
9471 void lp_set_posix_pathnames(void)
9472 {
9473         posix_pathnames = True;
9474 }
9475
9476 /*******************************************************************
9477  Global state for POSIX lock processing - CIFS unix extensions.
9478 ********************************************************************/
9479
9480 bool posix_default_lock_was_set;
9481 static enum brl_flavour posix_cifsx_locktype; /* By default 0 == WINDOWS_LOCK */
9482
9483 enum brl_flavour lp_posix_cifsu_locktype(files_struct *fsp)
9484 {
9485         if (posix_default_lock_was_set) {
9486                 return posix_cifsx_locktype;
9487         } else {
9488                 return fsp->posix_open ? POSIX_LOCK : WINDOWS_LOCK;
9489         }
9490 }
9491
9492 /*******************************************************************
9493 ********************************************************************/
9494
9495 void lp_set_posix_default_cifsx_readwrite_locktype(enum brl_flavour val)
9496 {
9497         posix_default_lock_was_set = True;
9498         posix_cifsx_locktype = val;
9499 }
9500
9501 int lp_min_receive_file_size(void)
9502 {
9503         if (Globals.iminreceivefile < 0) {
9504                 return 0;
9505         }
9506         return MIN(Globals.iminreceivefile, BUFFER_SIZE);
9507 }