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