s3:loadparm: add lp_local_ptr() that operates on a service struct
[ira/wip.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  * Free the allocated data for one parameter for a given share.
4590  */
4591 static void free_parameter(int snum, struct parm_struct parm)
4592 {
4593         void *parm_ptr;
4594
4595         if (parm.ptr == NULL); {
4596                 return;
4597         }
4598
4599         if (snum < 0) {
4600                 parm_ptr = parm.ptr;
4601         } else if (parm.p_class != P_LOCAL) {
4602                 return;
4603         } else {
4604                 parm_ptr = lp_local_ptr_by_snum(snum, parm.ptr);
4605         }
4606
4607         if ((parm.type == P_STRING) ||
4608             (parm.type == P_USTRING))
4609         {
4610                 string_free((char**)parm_ptr);
4611         } else if (parm.type == P_LIST) {
4612                 TALLOC_FREE(*((char***)parm_ptr));
4613         }
4614 }
4615
4616 /**
4617  * Free the allocated parameter data for a share.
4618  */
4619 static void free_parameters(int snum)
4620 {
4621         uint32_t i;
4622
4623         for (i=0; parm_table[i].label; i++) {
4624                 free_parameter(snum, parm_table[i]);
4625         }
4626 }
4627
4628 /**
4629  * Free the allocated global parameters.
4630  */
4631 static void free_global_parameters(void)
4632 {
4633         free_parameters(GLOBAL_SECTION_SNUM);
4634 }
4635
4636 /***************************************************************************
4637  Initialise the global parameter structure.
4638 ***************************************************************************/
4639
4640 static void init_globals(bool first_time_only)
4641 {
4642         static bool done_init = False;
4643         char *s = NULL;
4644         int i;
4645
4646         /* If requested to initialize only once and we've already done it... */
4647         if (first_time_only && done_init) {
4648                 /* ... then we have nothing more to do */
4649                 return;
4650         }
4651
4652         if (!done_init) {
4653                 /* The logfile can be set before this is invoked. Free it if so. */
4654                 if (Globals.szLogFile != NULL) {
4655                         string_free(&Globals.szLogFile);
4656                         Globals.szLogFile = NULL;
4657                 }
4658                 done_init = True;
4659         } else {
4660                 free_global_parameters();
4661         }
4662
4663         memset((void *)&Globals, '\0', sizeof(Globals));
4664
4665         for (i = 0; parm_table[i].label; i++) {
4666                 if ((parm_table[i].type == P_STRING ||
4667                      parm_table[i].type == P_USTRING) &&
4668                     parm_table[i].ptr)
4669                 {
4670                         string_set((char **)parm_table[i].ptr, "");
4671                 }
4672         }
4673
4674         string_set(&sDefault.fstype, FSTYPE_STRING);
4675         string_set(&sDefault.szPrintjobUsername, "%U");
4676
4677         init_printer_values(&sDefault);
4678
4679
4680         DEBUG(3, ("Initialising global parameters\n"));
4681
4682         string_set(&Globals.szSMBPasswdFile, get_dyn_SMB_PASSWD_FILE());
4683         string_set(&Globals.szPrivateDir, get_dyn_PRIVATE_DIR());
4684
4685         /* use the new 'hash2' method by default, with a prefix of 1 */
4686         string_set(&Globals.szManglingMethod, "hash2");
4687         Globals.mangle_prefix = 1;
4688
4689         string_set(&Globals.szGuestaccount, GUEST_ACCOUNT);
4690
4691         /* using UTF8 by default allows us to support all chars */
4692         string_set(&Globals.unix_charset, DEFAULT_UNIX_CHARSET);
4693
4694 #if defined(HAVE_NL_LANGINFO) && defined(CODESET)
4695         /* If the system supports nl_langinfo(), try to grab the value
4696            from the user's locale */
4697         string_set(&Globals.display_charset, "LOCALE");
4698 #else
4699         string_set(&Globals.display_charset, DEFAULT_DISPLAY_CHARSET);
4700 #endif
4701
4702         /* Use codepage 850 as a default for the dos character set */
4703         string_set(&Globals.dos_charset, DEFAULT_DOS_CHARSET);
4704
4705         /*
4706          * Allow the default PASSWD_CHAT to be overridden in local.h.
4707          */
4708         string_set(&Globals.szPasswdChat, DEFAULT_PASSWD_CHAT);
4709
4710         set_global_myname(myhostname());
4711         string_set(&Globals.szNetbiosName,global_myname());
4712
4713         set_global_myworkgroup(WORKGROUP);
4714         string_set(&Globals.szWorkgroup, lp_workgroup());
4715
4716         string_set(&Globals.szPasswdProgram, "");
4717         string_set(&Globals.szPidDir, get_dyn_PIDDIR());
4718         string_set(&Globals.szLockDir, get_dyn_LOCKDIR());
4719         string_set(&Globals.szSocketAddress, "0.0.0.0");
4720
4721         if (asprintf(&s, "Samba %s", SAMBA_VERSION_STRING) < 0) {
4722                 smb_panic("init_globals: ENOMEM");
4723         }
4724         string_set(&Globals.szServerString, s);
4725         SAFE_FREE(s);
4726         if (asprintf(&s, "%d.%d", DEFAULT_MAJOR_VERSION,
4727                         DEFAULT_MINOR_VERSION) < 0) {
4728                 smb_panic("init_globals: ENOMEM");
4729         }
4730         string_set(&Globals.szAnnounceVersion, s);
4731         SAFE_FREE(s);
4732 #ifdef DEVELOPER
4733         string_set(&Globals.szPanicAction, "/bin/sleep 999999999");
4734 #endif
4735
4736         string_set(&Globals.szSocketOptions, DEFAULT_SOCKET_OPTIONS);
4737
4738         string_set(&Globals.szLogonDrive, "");
4739         /* %N is the NIS auto.home server if -DAUTOHOME is used, else same as %L */
4740         string_set(&Globals.szLogonHome, "\\\\%N\\%U");
4741         string_set(&Globals.szLogonPath, "\\\\%N\\%U\\profile");
4742
4743         string_set(&Globals.szNameResolveOrder, "lmhosts wins host bcast");
4744         string_set(&Globals.szPasswordServer, "*");
4745
4746         Globals.AlgorithmicRidBase = BASE_RID;
4747
4748         Globals.bLoadPrinters = True;
4749         Globals.PrintcapCacheTime = 750;        /* 12.5 minutes */
4750
4751         Globals.ConfigBackend = config_backend;
4752
4753         /* Was 65535 (0xFFFF). 0x4101 matches W2K and causes major speed improvements... */
4754         /* Discovered by 2 days of pain by Don McCall @ HP :-). */
4755         Globals.max_xmit = 0x4104;
4756         Globals.max_mux = 50;   /* This is *needed* for profile support. */
4757         Globals.lpqcachetime = 30;      /* changed to handle large print servers better -- jerry */
4758         Globals.bDisableSpoolss = False;
4759         Globals.iMaxSmbdProcesses = 0;/* no limit specified */
4760         Globals.pwordlevel = 0;
4761         Globals.unamelevel = 0;
4762         Globals.deadtime = 0;
4763         Globals.getwd_cache = true;
4764         Globals.bLargeReadwrite = True;
4765         Globals.max_log_size = 5000;
4766         Globals.max_open_files = MAX_OPEN_FILES;
4767         Globals.open_files_db_hash_size = SMB_OPEN_DATABASE_TDB_HASH_SIZE;
4768         Globals.maxprotocol = PROTOCOL_NT1;
4769         Globals.minprotocol = PROTOCOL_CORE;
4770         Globals.security = SEC_USER;
4771         Globals.paranoid_server_security = True;
4772         Globals.bEncryptPasswords = True;
4773         Globals.bUpdateEncrypt = False;
4774         Globals.clientSchannel = Auto;
4775         Globals.serverSchannel = Auto;
4776         Globals.bReadRaw = True;
4777         Globals.bWriteRaw = True;
4778         Globals.bNullPasswords = False;
4779         Globals.bObeyPamRestrictions = False;
4780         Globals.syslog = 1;
4781         Globals.bSyslogOnly = False;
4782         Globals.bTimestampLogs = True;
4783         string_set(&Globals.szLogLevel, "0");
4784         Globals.bDebugPrefixTimestamp = False;
4785         Globals.bDebugHiresTimestamp = False;
4786         Globals.bDebugPid = False;
4787         Globals.bDebugUid = False;
4788         Globals.bDebugClass = False;
4789         Globals.bEnableCoreFiles = True;
4790         Globals.max_ttl = 60 * 60 * 24 * 3;     /* 3 days default. */
4791         Globals.max_wins_ttl = 60 * 60 * 24 * 6;        /* 6 days default. */
4792         Globals.min_wins_ttl = 60 * 60 * 6;     /* 6 hours default. */
4793         Globals.machine_password_timeout = 60 * 60 * 24 * 7;    /* 7 days default. */
4794         Globals.lm_announce = 2;        /* = Auto: send only if LM clients found */
4795         Globals.lm_interval = 60;
4796         Globals.announce_as = ANNOUNCE_AS_NT_SERVER;
4797 #if (defined(HAVE_NETGROUP) && defined(WITH_AUTOMOUNT))
4798         Globals.bNISHomeMap = False;
4799 #ifdef WITH_NISPLUS_HOME
4800         string_set(&Globals.szNISHomeMapName, "auto_home.org_dir");
4801 #else
4802         string_set(&Globals.szNISHomeMapName, "auto.home");
4803 #endif
4804 #endif
4805         Globals.bTimeServer = False;
4806         Globals.bBindInterfacesOnly = False;
4807         Globals.bUnixPasswdSync = False;
4808         Globals.bPamPasswordChange = False;
4809         Globals.bPasswdChatDebug = False;
4810         Globals.iPasswdChatTimeout = 2; /* 2 second default. */
4811         Globals.bNTPipeSupport = True;  /* Do NT pipes by default. */
4812         Globals.bNTStatusSupport = True; /* Use NT status by default. */
4813         Globals.bStatCache = True;      /* use stat cache by default */
4814         Globals.iMaxStatCacheSize = 256; /* 256k by default */
4815         Globals.restrict_anonymous = 0;
4816         Globals.bClientLanManAuth = False;      /* Do NOT use the LanMan hash if it is available */
4817         Globals.bClientPlaintextAuth = False;   /* Do NOT use a plaintext password even if is requested by the server */
4818         Globals.bLanmanAuth = False;    /* Do NOT use the LanMan hash, even if it is supplied */
4819         Globals.bNTLMAuth = True;       /* Do use NTLMv1 if it is supplied by the client (otherwise NTLMv2) */
4820         Globals.bClientNTLMv2Auth = False; /* Client should not use NTLMv2, as we can't tell that the server supports it. */
4821         /* Note, that we will use NTLM2 session security (which is different), if it is available */
4822
4823         Globals.map_to_guest = 0;       /* By Default, "Never" */
4824         Globals.oplock_break_wait_time = 0;     /* By Default, 0 msecs. */
4825         Globals.enhanced_browsing = true;
4826         Globals.iLockSpinTime = WINDOWS_MINIMUM_LOCK_TIMEOUT_MS; /* msec. */
4827 #ifdef MMAP_BLACKLIST
4828         Globals.bUseMmap = False;
4829 #else
4830         Globals.bUseMmap = True;
4831 #endif
4832         Globals.bUnixExtensions = True;
4833         Globals.bResetOnZeroVC = False;
4834
4835         /* hostname lookups can be very expensive and are broken on
4836            a large number of sites (tridge) */
4837         Globals.bHostnameLookups = False;
4838
4839         string_set(&Globals.szPassdbBackend, "smbpasswd");
4840         string_set(&Globals.szLdapSuffix, "");
4841         string_set(&Globals.szLdapMachineSuffix, "");
4842         string_set(&Globals.szLdapUserSuffix, "");
4843         string_set(&Globals.szLdapGroupSuffix, "");
4844         string_set(&Globals.szLdapIdmapSuffix, "");
4845
4846         string_set(&Globals.szLdapAdminDn, "");
4847         Globals.ldap_ssl = LDAP_SSL_ON;
4848         Globals.ldap_passwd_sync = LDAP_PASSWD_SYNC_OFF;
4849         Globals.ldap_delete_dn = False;
4850         Globals.ldap_replication_sleep = 1000; /* wait 1 sec for replication */
4851         Globals.ldap_timeout = LDAP_DEFAULT_TIMEOUT;
4852         Globals.ldap_connection_timeout = LDAP_CONNECTION_DEFAULT_TIMEOUT;
4853         Globals.ldap_page_size = LDAP_PAGE_SIZE;
4854
4855         Globals.ldap_debug_level = 0;
4856         Globals.ldap_debug_threshold = 10;
4857
4858         /* This is what we tell the afs client. in reality we set the token 
4859          * to never expire, though, when this runs out the afs client will 
4860          * forget the token. Set to 0 to get NEVERDATE.*/
4861         Globals.iAfsTokenLifetime = 604800;
4862         Globals.cups_connection_timeout = CUPS_DEFAULT_CONNECTION_TIMEOUT;
4863
4864 /* these parameters are set to defaults that are more appropriate
4865    for the increasing samba install base:
4866
4867    as a member of the workgroup, that will possibly become a
4868    _local_ master browser (lm = True).  this is opposed to a forced
4869    local master browser startup (pm = True).
4870
4871    doesn't provide WINS server service by default (wsupp = False),
4872    and doesn't provide domain master browser services by default, either.
4873
4874 */
4875
4876         Globals.bMsAddPrinterWizard = True;
4877         Globals.os_level = 20;
4878         Globals.bLocalMaster = True;
4879         Globals.iDomainMaster = Auto;   /* depending on bDomainLogons */
4880         Globals.bDomainLogons = False;
4881         Globals.bBrowseList = True;
4882         Globals.bWINSsupport = False;
4883         Globals.bWINSproxy = False;
4884
4885         TALLOC_FREE(Globals.szInitLogonDelayedHosts);
4886         Globals.InitLogonDelay = 100; /* 100 ms default delay */
4887
4888         Globals.bDNSproxy = True;
4889
4890         /* this just means to use them if they exist */
4891         Globals.bKernelOplocks = True;
4892
4893         Globals.bAllowTrustedDomains = True;
4894         string_set(&Globals.szIdmapBackend, "tdb");
4895
4896         string_set(&Globals.szTemplateShell, "/bin/false");
4897         string_set(&Globals.szTemplateHomedir, "/home/%D/%U");
4898         string_set(&Globals.szWinbindSeparator, "\\");
4899
4900         string_set(&Globals.szCupsServer, "");
4901         string_set(&Globals.szIPrintServer, "");
4902
4903         string_set(&Globals.ctdbdSocket, "");
4904         Globals.szClusterAddresses = NULL;
4905         Globals.clustering = False;
4906
4907         Globals.winbind_cache_time = 300;       /* 5 minutes */
4908         Globals.winbind_reconnect_delay = 30;   /* 30 seconds */
4909         Globals.bWinbindEnumUsers = False;
4910         Globals.bWinbindEnumGroups = False;
4911         Globals.bWinbindUseDefaultDomain = False;
4912         Globals.bWinbindTrustedDomainsOnly = False;
4913         Globals.bWinbindNestedGroups = True;
4914         Globals.winbind_expand_groups = 1;
4915         Globals.szWinbindNssInfo = str_list_make_v3(talloc_autofree_context(), "template", NULL);
4916         Globals.bWinbindRefreshTickets = False;
4917         Globals.bWinbindOfflineLogon = False;
4918
4919         Globals.iIdmapCacheTime = 86400 * 7; /* a week by default */
4920         Globals.iIdmapNegativeCacheTime = 120; /* 2 minutes by default */
4921
4922         Globals.bPassdbExpandExplicit = False;
4923
4924         Globals.name_cache_timeout = 660; /* In seconds */
4925
4926         Globals.bUseSpnego = True;
4927         Globals.bClientUseSpnego = True;
4928
4929         Globals.client_signing = Auto;
4930         Globals.server_signing = False;
4931
4932         Globals.bDeferSharingViolations = True;
4933         string_set(&Globals.smb_ports, SMB_PORTS);
4934
4935         Globals.bEnablePrivileges = True;
4936         Globals.bHostMSDfs        = True;
4937         Globals.bASUSupport       = False;
4938
4939         /* User defined shares. */
4940         if (asprintf(&s, "%s/usershares", get_dyn_STATEDIR()) < 0) {
4941                 smb_panic("init_globals: ENOMEM");
4942         }
4943         string_set(&Globals.szUsersharePath, s);
4944         SAFE_FREE(s);
4945         string_set(&Globals.szUsershareTemplateShare, "");
4946         Globals.iUsershareMaxShares = 0;
4947         /* By default disallow sharing of directories not owned by the sharer. */
4948         Globals.bUsershareOwnerOnly = True;
4949         /* By default disallow guest access to usershares. */
4950         Globals.bUsershareAllowGuests = False;
4951
4952         Globals.iKeepalive = DEFAULT_KEEPALIVE;
4953
4954         /* By default no shares out of the registry */
4955         Globals.bRegistryShares = False;
4956
4957         Globals.iminreceivefile = 0;
4958 }
4959
4960 /*******************************************************************
4961  Convenience routine to grab string parameters into temporary memory
4962  and run standard_sub_basic on them. The buffers can be written to by
4963  callers without affecting the source string.
4964 ********************************************************************/
4965
4966 static char *lp_string(const char *s)
4967 {
4968         char *ret;
4969         TALLOC_CTX *ctx = talloc_tos();
4970
4971         /* The follow debug is useful for tracking down memory problems
4972            especially if you have an inner loop that is calling a lp_*()
4973            function that returns a string.  Perhaps this debug should be
4974            present all the time? */
4975
4976 #if 0
4977         DEBUG(10, ("lp_string(%s)\n", s));
4978 #endif
4979
4980         ret = talloc_sub_basic(ctx,
4981                         get_current_username(),
4982                         current_user_info.domain,
4983                         s);
4984         if (trim_char(ret, '\"', '\"')) {
4985                 if (strchr(ret,'\"') != NULL) {
4986                         TALLOC_FREE(ret);
4987                         ret = talloc_sub_basic(ctx,
4988                                         get_current_username(),
4989                                         current_user_info.domain,
4990                                         s);
4991                 }
4992         }
4993         return ret;
4994 }
4995
4996 /*
4997    In this section all the functions that are used to access the 
4998    parameters from the rest of the program are defined 
4999 */
5000
5001 #define FN_GLOBAL_STRING(fn_name,ptr) \
5002  char *fn_name(void) {return(lp_string(*(char **)(ptr) ? *(char **)(ptr) : ""));}
5003 #define FN_GLOBAL_CONST_STRING(fn_name,ptr) \
5004  const char *fn_name(void) {return(*(const char **)(ptr) ? *(const char **)(ptr) : "");}
5005 #define FN_GLOBAL_LIST(fn_name,ptr) \
5006  const char **fn_name(void) {return(*(const char ***)(ptr));}
5007 #define FN_GLOBAL_BOOL(fn_name,ptr) \
5008  bool fn_name(void) {return(*(bool *)(ptr));}
5009 #define FN_GLOBAL_CHAR(fn_name,ptr) \
5010  char fn_name(void) {return(*(char *)(ptr));}
5011 #define FN_GLOBAL_INTEGER(fn_name,ptr) \
5012  int fn_name(void) {return(*(int *)(ptr));}
5013
5014 #define FN_LOCAL_STRING(fn_name,val) \
5015  char *fn_name(int i) {return(lp_string((LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val));}
5016 #define FN_LOCAL_CONST_STRING(fn_name,val) \
5017  const char *fn_name(int i) {return (const char *)((LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val);}
5018 #define FN_LOCAL_LIST(fn_name,val) \
5019  const char **fn_name(int i) {return(const char **)(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
5020 #define FN_LOCAL_BOOL(fn_name,val) \
5021  bool fn_name(int i) {return(bool)(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
5022 #define FN_LOCAL_INTEGER(fn_name,val) \
5023  int fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
5024
5025 #define FN_LOCAL_PARM_BOOL(fn_name,val) \
5026  bool fn_name(const struct share_params *p) {return(bool)(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
5027 #define FN_LOCAL_PARM_INTEGER(fn_name,val) \
5028  int fn_name(const struct share_params *p) {return(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
5029 #define FN_LOCAL_PARM_STRING(fn_name,val) \
5030  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));}
5031 #define FN_LOCAL_CHAR(fn_name,val) \
5032  char fn_name(const struct share_params *p) {return(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
5033
5034 FN_GLOBAL_STRING(lp_smb_ports, &Globals.smb_ports)
5035 FN_GLOBAL_STRING(lp_dos_charset, &Globals.dos_charset)
5036 FN_GLOBAL_STRING(lp_unix_charset, &Globals.unix_charset)
5037 FN_GLOBAL_STRING(lp_display_charset, &Globals.display_charset)
5038 FN_GLOBAL_STRING(lp_logfile, &Globals.szLogFile)
5039 FN_GLOBAL_STRING(lp_configfile, &Globals.szConfigFile)
5040 FN_GLOBAL_STRING(lp_smb_passwd_file, &Globals.szSMBPasswdFile)
5041 FN_GLOBAL_STRING(lp_private_dir, &Globals.szPrivateDir)
5042 FN_GLOBAL_STRING(lp_serverstring, &Globals.szServerString)
5043 FN_GLOBAL_INTEGER(lp_printcap_cache_time, &Globals.PrintcapCacheTime)
5044 FN_GLOBAL_STRING(lp_addport_cmd, &Globals.szAddPortCommand)
5045 FN_GLOBAL_STRING(lp_enumports_cmd, &Globals.szEnumPortsCommand)
5046 FN_GLOBAL_STRING(lp_addprinter_cmd, &Globals.szAddPrinterCommand)
5047 FN_GLOBAL_STRING(lp_deleteprinter_cmd, &Globals.szDeletePrinterCommand)
5048 FN_GLOBAL_STRING(lp_os2_driver_map, &Globals.szOs2DriverMap)
5049 FN_GLOBAL_STRING(lp_lockdir, &Globals.szLockDir)
5050 FN_GLOBAL_STRING(lp_piddir, &Globals.szPidDir)
5051 FN_GLOBAL_STRING(lp_mangling_method, &Globals.szManglingMethod)
5052 FN_GLOBAL_INTEGER(lp_mangle_prefix, &Globals.mangle_prefix)
5053 FN_GLOBAL_STRING(lp_utmpdir, &Globals.szUtmpDir)
5054 FN_GLOBAL_STRING(lp_wtmpdir, &Globals.szWtmpDir)
5055 FN_GLOBAL_BOOL(lp_utmp, &Globals.bUtmp)
5056 FN_GLOBAL_STRING(lp_rootdir, &Globals.szRootdir)
5057 FN_GLOBAL_STRING(lp_defaultservice, &Globals.szDefaultService)
5058 FN_GLOBAL_STRING(lp_msg_command, &Globals.szMsgCommand)
5059 FN_GLOBAL_STRING(lp_get_quota_command, &Globals.szGetQuota)
5060 FN_GLOBAL_STRING(lp_set_quota_command, &Globals.szSetQuota)
5061 FN_GLOBAL_STRING(lp_auto_services, &Globals.szAutoServices)
5062 FN_GLOBAL_STRING(lp_passwd_program, &Globals.szPasswdProgram)
5063 FN_GLOBAL_STRING(lp_passwd_chat, &Globals.szPasswdChat)
5064 FN_GLOBAL_STRING(lp_passwordserver, &Globals.szPasswordServer)
5065 FN_GLOBAL_STRING(lp_name_resolve_order, &Globals.szNameResolveOrder)
5066 FN_GLOBAL_STRING(lp_realm, &Globals.szRealm)
5067 FN_GLOBAL_CONST_STRING(lp_afs_username_map, &Globals.szAfsUsernameMap)
5068 FN_GLOBAL_INTEGER(lp_afs_token_lifetime, &Globals.iAfsTokenLifetime)
5069 FN_GLOBAL_STRING(lp_log_nt_token_command, &Globals.szLogNtTokenCommand)
5070 FN_GLOBAL_STRING(lp_username_map, &Globals.szUsernameMap)
5071 FN_GLOBAL_CONST_STRING(lp_logon_script, &Globals.szLogonScript)
5072 FN_GLOBAL_CONST_STRING(lp_logon_path, &Globals.szLogonPath)
5073 FN_GLOBAL_CONST_STRING(lp_logon_drive, &Globals.szLogonDrive)
5074 FN_GLOBAL_CONST_STRING(lp_logon_home, &Globals.szLogonHome)
5075 FN_GLOBAL_STRING(lp_remote_announce, &Globals.szRemoteAnnounce)
5076 FN_GLOBAL_STRING(lp_remote_browse_sync, &Globals.szRemoteBrowseSync)
5077 FN_GLOBAL_LIST(lp_wins_server_list, &Globals.szWINSservers)
5078 FN_GLOBAL_LIST(lp_interfaces, &Globals.szInterfaces)
5079 FN_GLOBAL_STRING(lp_nis_home_map_name, &Globals.szNISHomeMapName)
5080 static FN_GLOBAL_STRING(lp_announce_version, &Globals.szAnnounceVersion)
5081 FN_GLOBAL_LIST(lp_netbios_aliases, &Globals.szNetbiosAliases)
5082 /* FN_GLOBAL_STRING(lp_passdb_backend, &Globals.szPassdbBackend)
5083  * lp_passdb_backend() should be replace by the this macro again after
5084  * some releases.
5085  * */
5086 const char *lp_passdb_backend(void)
5087 {
5088         char *delim, *quote;
5089
5090         delim = strchr( Globals.szPassdbBackend, ' ');
5091         /* no space at all */
5092         if (delim == NULL) {
5093                 goto out;
5094         }
5095
5096         quote = strchr(Globals.szPassdbBackend, '"');
5097         /* no quote char or non in the first part */
5098         if (quote == NULL || quote > delim) {
5099                 *delim = '\0';
5100                 goto warn;
5101         }
5102
5103         quote = strchr(quote+1, '"');
5104         if (quote == NULL) {
5105                 DEBUG(0, ("WARNING: Your 'passdb backend' configuration is invalid due to a missing second \" char.\n"));
5106                 goto out;
5107         } else if (*(quote+1) == '\0') {
5108                 /* space, fitting quote char, and one backend only */
5109                 goto out;
5110         } else {
5111                 /* terminate string after the fitting quote char */
5112                 *(quote+1) = '\0';
5113         }
5114
5115 warn:
5116         DEBUG(0, ("WARNING: Your 'passdb backend' configuration includes multiple backends.  This\n"
5117                 "is deprecated since Samba 3.0.23.  Please check WHATSNEW.txt or the section 'Passdb\n"
5118                 "Changes' from the ChangeNotes as part of the Samba HOWTO collection.  Only the first\n"
5119                 "backend (%s) is used.  The rest is ignored.\n", Globals.szPassdbBackend));
5120
5121 out:
5122         return Globals.szPassdbBackend;
5123 }
5124 FN_GLOBAL_LIST(lp_preload_modules, &Globals.szPreloadModules)
5125 FN_GLOBAL_STRING(lp_panic_action, &Globals.szPanicAction)
5126 FN_GLOBAL_STRING(lp_adduser_script, &Globals.szAddUserScript)
5127 FN_GLOBAL_STRING(lp_renameuser_script, &Globals.szRenameUserScript)
5128 FN_GLOBAL_STRING(lp_deluser_script, &Globals.szDelUserScript)
5129
5130 FN_GLOBAL_CONST_STRING(lp_guestaccount, &Globals.szGuestaccount)
5131 FN_GLOBAL_STRING(lp_addgroup_script, &Globals.szAddGroupScript)
5132 FN_GLOBAL_STRING(lp_delgroup_script, &Globals.szDelGroupScript)
5133 FN_GLOBAL_STRING(lp_addusertogroup_script, &Globals.szAddUserToGroupScript)
5134 FN_GLOBAL_STRING(lp_deluserfromgroup_script, &Globals.szDelUserFromGroupScript)
5135 FN_GLOBAL_STRING(lp_setprimarygroup_script, &Globals.szSetPrimaryGroupScript)
5136
5137 FN_GLOBAL_STRING(lp_addmachine_script, &Globals.szAddMachineScript)
5138
5139 FN_GLOBAL_STRING(lp_shutdown_script, &Globals.szShutdownScript)
5140 FN_GLOBAL_STRING(lp_abort_shutdown_script, &Globals.szAbortShutdownScript)
5141 FN_GLOBAL_STRING(lp_username_map_script, &Globals.szUsernameMapScript)
5142
5143 FN_GLOBAL_STRING(lp_check_password_script, &Globals.szCheckPasswordScript)
5144
5145 FN_GLOBAL_STRING(lp_wins_hook, &Globals.szWINSHook)
5146 FN_GLOBAL_CONST_STRING(lp_template_homedir, &Globals.szTemplateHomedir)
5147 FN_GLOBAL_CONST_STRING(lp_template_shell, &Globals.szTemplateShell)
5148 FN_GLOBAL_CONST_STRING(lp_winbind_separator, &Globals.szWinbindSeparator)
5149 FN_GLOBAL_INTEGER(lp_acl_compatibility, &Globals.iAclCompat)
5150 FN_GLOBAL_BOOL(lp_winbind_enum_users, &Globals.bWinbindEnumUsers)
5151 FN_GLOBAL_BOOL(lp_winbind_enum_groups, &Globals.bWinbindEnumGroups)
5152 FN_GLOBAL_BOOL(lp_winbind_use_default_domain, &Globals.bWinbindUseDefaultDomain)
5153 FN_GLOBAL_BOOL(lp_winbind_trusted_domains_only, &Globals.bWinbindTrustedDomainsOnly)
5154 FN_GLOBAL_BOOL(lp_winbind_nested_groups, &Globals.bWinbindNestedGroups)
5155 FN_GLOBAL_INTEGER(lp_winbind_expand_groups, &Globals.winbind_expand_groups)
5156 FN_GLOBAL_BOOL(lp_winbind_refresh_tickets, &Globals.bWinbindRefreshTickets)
5157 FN_GLOBAL_BOOL(lp_winbind_offline_logon, &Globals.bWinbindOfflineLogon)
5158 FN_GLOBAL_BOOL(lp_winbind_normalize_names, &Globals.bWinbindNormalizeNames)
5159 FN_GLOBAL_BOOL(lp_winbind_rpc_only, &Globals.bWinbindRpcOnly)
5160
5161 FN_GLOBAL_CONST_STRING(lp_idmap_backend, &Globals.szIdmapBackend)
5162 FN_GLOBAL_STRING(lp_idmap_alloc_backend, &Globals.szIdmapAllocBackend)
5163 FN_GLOBAL_INTEGER(lp_idmap_cache_time, &Globals.iIdmapCacheTime)
5164 FN_GLOBAL_INTEGER(lp_idmap_negative_cache_time, &Globals.iIdmapNegativeCacheTime)
5165 FN_GLOBAL_INTEGER(lp_keepalive, &Globals.iKeepalive)
5166 FN_GLOBAL_BOOL(lp_passdb_expand_explicit, &Globals.bPassdbExpandExplicit)
5167
5168 FN_GLOBAL_STRING(lp_ldap_suffix, &Globals.szLdapSuffix)
5169 FN_GLOBAL_STRING(lp_ldap_admin_dn, &Globals.szLdapAdminDn)
5170 FN_GLOBAL_INTEGER(lp_ldap_ssl, &Globals.ldap_ssl)
5171 FN_GLOBAL_INTEGER(lp_ldap_passwd_sync, &Globals.ldap_passwd_sync)
5172 FN_GLOBAL_BOOL(lp_ldap_delete_dn, &Globals.ldap_delete_dn)
5173 FN_GLOBAL_INTEGER(lp_ldap_replication_sleep, &Globals.ldap_replication_sleep)
5174 FN_GLOBAL_INTEGER(lp_ldap_timeout, &Globals.ldap_timeout)
5175 FN_GLOBAL_INTEGER(lp_ldap_connection_timeout, &Globals.ldap_connection_timeout)
5176 FN_GLOBAL_INTEGER(lp_ldap_page_size, &Globals.ldap_page_size)
5177 FN_GLOBAL_INTEGER(lp_ldap_debug_level, &Globals.ldap_debug_level)
5178 FN_GLOBAL_INTEGER(lp_ldap_debug_threshold, &Globals.ldap_debug_threshold)
5179 FN_GLOBAL_STRING(lp_add_share_cmd, &Globals.szAddShareCommand)
5180 FN_GLOBAL_STRING(lp_change_share_cmd, &Globals.szChangeShareCommand)
5181 FN_GLOBAL_STRING(lp_delete_share_cmd, &Globals.szDeleteShareCommand)
5182 FN_GLOBAL_STRING(lp_usershare_path, &Globals.szUsersharePath)
5183 FN_GLOBAL_LIST(lp_usershare_prefix_allow_list, &Globals.szUsersharePrefixAllowList)
5184 FN_GLOBAL_LIST(lp_usershare_prefix_deny_list, &Globals.szUsersharePrefixDenyList)
5185
5186 FN_GLOBAL_LIST(lp_eventlog_list, &Globals.szEventLogs)
5187
5188 FN_GLOBAL_BOOL(lp_registry_shares, &Globals.bRegistryShares)
5189 FN_GLOBAL_BOOL(lp_usershare_allow_guests, &Globals.bUsershareAllowGuests)
5190 FN_GLOBAL_BOOL(lp_usershare_owner_only, &Globals.bUsershareOwnerOnly)
5191 FN_GLOBAL_BOOL(lp_disable_netbios, &Globals.bDisableNetbios)
5192 FN_GLOBAL_BOOL(lp_reset_on_zero_vc, &Globals.bResetOnZeroVC)
5193 FN_GLOBAL_BOOL(lp_ms_add_printer_wizard, &Globals.bMsAddPrinterWizard)
5194 FN_GLOBAL_BOOL(lp_dns_proxy, &Globals.bDNSproxy)
5195 FN_GLOBAL_BOOL(lp_wins_support, &Globals.bWINSsupport)
5196 FN_GLOBAL_BOOL(lp_we_are_a_wins_server, &Globals.bWINSsupport)
5197 FN_GLOBAL_BOOL(lp_wins_proxy, &Globals.bWINSproxy)
5198 FN_GLOBAL_BOOL(lp_local_master, &Globals.bLocalMaster)
5199 FN_GLOBAL_BOOL(lp_domain_logons, &Globals.bDomainLogons)
5200 FN_GLOBAL_LIST(lp_init_logon_delayed_hosts, &Globals.szInitLogonDelayedHosts)
5201 FN_GLOBAL_INTEGER(lp_init_logon_delay, &Globals.InitLogonDelay)
5202 FN_GLOBAL_BOOL(lp_load_printers, &Globals.bLoadPrinters)
5203 FN_GLOBAL_BOOL(lp_readraw, &Globals.bReadRaw)
5204 FN_GLOBAL_BOOL(lp_large_readwrite, &Globals.bLargeReadwrite)
5205 FN_GLOBAL_BOOL(lp_writeraw, &Globals.bWriteRaw)
5206 FN_GLOBAL_BOOL(lp_null_passwords, &Globals.bNullPasswords)
5207 FN_GLOBAL_BOOL(lp_obey_pam_restrictions, &Globals.bObeyPamRestrictions)
5208 FN_GLOBAL_BOOL(lp_encrypted_passwords, &Globals.bEncryptPasswords)
5209 FN_GLOBAL_BOOL(lp_update_encrypted, &Globals.bUpdateEncrypt)
5210 FN_GLOBAL_INTEGER(lp_client_schannel, &Globals.clientSchannel)
5211 FN_GLOBAL_INTEGER(lp_server_schannel, &Globals.serverSchannel)
5212 FN_GLOBAL_BOOL(lp_syslog_only, &Globals.bSyslogOnly)
5213 FN_GLOBAL_BOOL(lp_timestamp_logs, &Globals.bTimestampLogs)
5214 FN_GLOBAL_BOOL(lp_debug_prefix_timestamp, &Globals.bDebugPrefixTimestamp)
5215 FN_GLOBAL_BOOL(lp_debug_hires_timestamp, &Globals.bDebugHiresTimestamp)
5216 FN_GLOBAL_BOOL(lp_debug_pid, &Globals.bDebugPid)
5217 FN_GLOBAL_BOOL(lp_debug_uid, &Globals.bDebugUid)
5218 FN_GLOBAL_BOOL(lp_debug_class, &Globals.bDebugClass)
5219 FN_GLOBAL_BOOL(lp_enable_core_files, &Globals.bEnableCoreFiles)
5220 FN_GLOBAL_BOOL(lp_browse_list, &Globals.bBrowseList)
5221 FN_GLOBAL_BOOL(lp_nis_home_map, &Globals.bNISHomeMap)
5222 static FN_GLOBAL_BOOL(lp_time_server, &Globals.bTimeServer)
5223 FN_GLOBAL_BOOL(lp_bind_interfaces_only, &Globals.bBindInterfacesOnly)
5224 FN_GLOBAL_BOOL(lp_pam_password_change, &Globals.bPamPasswordChange)
5225 FN_GLOBAL_BOOL(lp_unix_password_sync, &Globals.bUnixPasswdSync)
5226 FN_GLOBAL_BOOL(lp_passwd_chat_debug, &Globals.bPasswdChatDebug)
5227 FN_GLOBAL_INTEGER(lp_passwd_chat_timeout, &Globals.iPasswdChatTimeout)
5228 FN_GLOBAL_BOOL(lp_nt_pipe_support, &Globals.bNTPipeSupport)
5229 FN_GLOBAL_BOOL(lp_nt_status_support, &Globals.bNTStatusSupport)
5230 FN_GLOBAL_BOOL(lp_stat_cache, &Globals.bStatCache)
5231 FN_GLOBAL_INTEGER(lp_max_stat_cache_size, &Globals.iMaxStatCacheSize)
5232 FN_GLOBAL_BOOL(lp_allow_trusted_domains, &Globals.bAllowTrustedDomains)
5233 FN_GLOBAL_INTEGER(lp_restrict_anonymous, &Globals.restrict_anonymous)
5234 FN_GLOBAL_BOOL(lp_lanman_auth, &Globals.bLanmanAuth)
5235 FN_GLOBAL_BOOL(lp_ntlm_auth, &Globals.bNTLMAuth)
5236 FN_GLOBAL_BOOL(lp_client_plaintext_auth, &Globals.bClientPlaintextAuth)
5237 FN_GLOBAL_BOOL(lp_client_lanman_auth, &Globals.bClientLanManAuth)
5238 FN_GLOBAL_BOOL(lp_client_ntlmv2_auth, &Globals.bClientNTLMv2Auth)
5239 FN_GLOBAL_BOOL(lp_host_msdfs, &Globals.bHostMSDfs)
5240 FN_GLOBAL_BOOL(lp_kernel_oplocks, &Globals.bKernelOplocks)
5241 FN_GLOBAL_BOOL(lp_enhanced_browsing, &Globals.enhanced_browsing)
5242 FN_GLOBAL_BOOL(lp_use_mmap, &Globals.bUseMmap)
5243 FN_GLOBAL_BOOL(lp_unix_extensions, &Globals.bUnixExtensions)
5244 FN_GLOBAL_BOOL(lp_use_spnego, &Globals.bUseSpnego)
5245 FN_GLOBAL_BOOL(lp_client_use_spnego, &Globals.bClientUseSpnego)
5246 FN_GLOBAL_BOOL(lp_hostname_lookups, &Globals.bHostnameLookups)
5247 FN_LOCAL_PARM_BOOL(lp_change_notify, bChangeNotify)
5248 FN_LOCAL_PARM_BOOL(lp_kernel_change_notify, bKernelChangeNotify)
5249 FN_GLOBAL_BOOL(lp_use_kerberos_keytab, &Globals.bUseKerberosKeytab)
5250 FN_GLOBAL_BOOL(lp_defer_sharing_violations, &Globals.bDeferSharingViolations)
5251 FN_GLOBAL_BOOL(lp_enable_privileges, &Globals.bEnablePrivileges)
5252 FN_GLOBAL_BOOL(lp_enable_asu_support, &Globals.bASUSupport)
5253 FN_GLOBAL_INTEGER(lp_os_level, &Globals.os_level)
5254 FN_GLOBAL_INTEGER(lp_max_ttl, &Globals.max_ttl)
5255 FN_GLOBAL_INTEGER(lp_max_wins_ttl, &Globals.max_wins_ttl)
5256 FN_GLOBAL_INTEGER(lp_min_wins_ttl, &Globals.min_wins_ttl)
5257 FN_GLOBAL_INTEGER(lp_max_log_size, &Globals.max_log_size)
5258 FN_GLOBAL_INTEGER(lp_max_open_files, &Globals.max_open_files)
5259 FN_GLOBAL_INTEGER(lp_open_files_db_hash_size, &Globals.open_files_db_hash_size)
5260 FN_GLOBAL_INTEGER(lp_maxxmit, &Globals.max_xmit)
5261 FN_GLOBAL_INTEGER(lp_maxmux, &Globals.max_mux)
5262 FN_GLOBAL_INTEGER(lp_passwordlevel, &Globals.pwordlevel)
5263 FN_GLOBAL_INTEGER(lp_usernamelevel, &Globals.unamelevel)
5264 FN_GLOBAL_INTEGER(lp_deadtime, &Globals.deadtime)
5265 FN_GLOBAL_BOOL(lp_getwd_cache, &Globals.getwd_cache)
5266 FN_GLOBAL_INTEGER(lp_maxprotocol, &Globals.maxprotocol)
5267 FN_GLOBAL_INTEGER(lp_minprotocol, &Globals.minprotocol)
5268 FN_GLOBAL_INTEGER(lp_security, &Globals.security)
5269 FN_GLOBAL_LIST(lp_auth_methods, &Globals.AuthMethods)
5270 FN_GLOBAL_BOOL(lp_paranoid_server_security, &Globals.paranoid_server_security)
5271 FN_GLOBAL_INTEGER(lp_maxdisksize, &Globals.maxdisksize)
5272 FN_GLOBAL_INTEGER(lp_lpqcachetime, &Globals.lpqcachetime)
5273 FN_GLOBAL_INTEGER(lp_max_smbd_processes, &Globals.iMaxSmbdProcesses)
5274 FN_GLOBAL_BOOL(_lp_disable_spoolss, &Globals.bDisableSpoolss)
5275 FN_GLOBAL_INTEGER(lp_syslog, &Globals.syslog)
5276 static FN_GLOBAL_INTEGER(lp_announce_as, &Globals.announce_as)
5277 FN_GLOBAL_INTEGER(lp_lm_announce, &Globals.lm_announce)
5278 FN_GLOBAL_INTEGER(lp_lm_interval, &Globals.lm_interval)
5279 FN_GLOBAL_INTEGER(lp_machine_password_timeout, &Globals.machine_password_timeout)
5280 FN_GLOBAL_INTEGER(lp_map_to_guest, &Globals.map_to_guest)
5281 FN_GLOBAL_INTEGER(lp_oplock_break_wait_time, &Globals.oplock_break_wait_time)
5282 FN_GLOBAL_INTEGER(lp_lock_spin_time, &Globals.iLockSpinTime)
5283 FN_GLOBAL_INTEGER(lp_usershare_max_shares, &Globals.iUsershareMaxShares)
5284 FN_GLOBAL_CONST_STRING(lp_socket_options, &Globals.szSocketOptions)
5285 FN_GLOBAL_INTEGER(lp_config_backend, &Globals.ConfigBackend)
5286
5287 FN_LOCAL_STRING(lp_preexec, szPreExec)
5288 FN_LOCAL_STRING(lp_postexec, szPostExec)
5289 FN_LOCAL_STRING(lp_rootpreexec, szRootPreExec)
5290 FN_LOCAL_STRING(lp_rootpostexec, szRootPostExec)
5291 FN_LOCAL_STRING(lp_servicename, szService)
5292 FN_LOCAL_CONST_STRING(lp_const_servicename, szService)
5293 FN_LOCAL_STRING(lp_pathname, szPath)
5294 FN_LOCAL_STRING(lp_dontdescend, szDontdescend)
5295 FN_LOCAL_STRING(lp_username, szUsername)
5296 FN_LOCAL_LIST(lp_invalid_users, szInvalidUsers)
5297 FN_LOCAL_LIST(lp_valid_users, szValidUsers)
5298 FN_LOCAL_LIST(lp_admin_users, szAdminUsers)
5299 FN_GLOBAL_LIST(lp_svcctl_list, &Globals.szServicesList)
5300 FN_LOCAL_STRING(lp_cups_options, szCupsOptions)
5301 FN_GLOBAL_STRING(lp_cups_server, &Globals.szCupsServer)
5302 FN_GLOBAL_STRING(lp_iprint_server, &Globals.szIPrintServer)
5303 FN_GLOBAL_INTEGER(lp_cups_connection_timeout, &Globals.cups_connection_timeout)
5304 FN_GLOBAL_CONST_STRING(lp_ctdbd_socket, &Globals.ctdbdSocket)
5305 FN_GLOBAL_LIST(lp_cluster_addresses, &Globals.szClusterAddresses)
5306 FN_GLOBAL_BOOL(lp_clustering, &Globals.clustering)
5307 FN_LOCAL_STRING(lp_printcommand, szPrintcommand)
5308 FN_LOCAL_STRING(lp_lpqcommand, szLpqcommand)
5309 FN_LOCAL_STRING(lp_lprmcommand, szLprmcommand)
5310 FN_LOCAL_STRING(lp_lppausecommand, szLppausecommand)
5311 FN_LOCAL_STRING(lp_lpresumecommand, szLpresumecommand)
5312 FN_LOCAL_STRING(lp_queuepausecommand, szQueuepausecommand)
5313 FN_LOCAL_STRING(lp_queueresumecommand, szQueueresumecommand)
5314 static FN_LOCAL_STRING(_lp_printername, szPrintername)
5315 FN_LOCAL_CONST_STRING(lp_printjob_username, szPrintjobUsername)
5316 FN_LOCAL_LIST(lp_hostsallow, szHostsallow)
5317 FN_LOCAL_LIST(lp_hostsdeny, szHostsdeny)
5318 FN_LOCAL_STRING(lp_magicscript, szMagicScript)
5319 FN_LOCAL_STRING(lp_magicoutput, szMagicOutput)
5320 FN_LOCAL_STRING(lp_comment, comment)
5321 FN_LOCAL_STRING(lp_force_user, force_user)
5322 FN_LOCAL_STRING(lp_force_group, force_group)
5323 FN_LOCAL_LIST(lp_readlist, readlist)
5324 FN_LOCAL_LIST(lp_writelist, writelist)
5325 FN_LOCAL_LIST(lp_printer_admin, printer_admin)
5326 FN_LOCAL_STRING(lp_fstype, fstype)
5327 FN_LOCAL_LIST(lp_vfs_objects, szVfsObjects)
5328 FN_LOCAL_STRING(lp_msdfs_proxy, szMSDfsProxy)
5329 static FN_LOCAL_STRING(lp_volume, volume)
5330 FN_LOCAL_STRING(lp_veto_files, szVetoFiles)
5331 FN_LOCAL_STRING(lp_hide_files, szHideFiles)
5332 FN_LOCAL_STRING(lp_veto_oplocks, szVetoOplockFiles)
5333 FN_LOCAL_BOOL(lp_msdfs_root, bMSDfsRoot)
5334 FN_LOCAL_STRING(lp_aio_write_behind, szAioWriteBehind)
5335 FN_LOCAL_STRING(lp_dfree_command, szDfree)
5336 FN_LOCAL_BOOL(lp_autoloaded, autoloaded)
5337 FN_LOCAL_BOOL(lp_preexec_close, bPreexecClose)
5338 FN_LOCAL_BOOL(lp_rootpreexec_close, bRootpreexecClose)
5339 FN_LOCAL_INTEGER(lp_casesensitive, iCaseSensitive)
5340 FN_LOCAL_BOOL(lp_preservecase, bCasePreserve)
5341 FN_LOCAL_BOOL(lp_shortpreservecase, bShortCasePreserve)
5342 FN_LOCAL_BOOL(lp_hide_dot_files, bHideDotFiles)
5343 FN_LOCAL_BOOL(lp_hide_special_files, bHideSpecialFiles)
5344 FN_LOCAL_BOOL(lp_hideunreadable, bHideUnReadable)
5345 FN_LOCAL_BOOL(lp_hideunwriteable_files, bHideUnWriteableFiles)
5346 FN_LOCAL_BOOL(lp_browseable, bBrowseable)
5347 FN_LOCAL_BOOL(lp_access_based_share_enum, bAccessBasedShareEnum)
5348 FN_LOCAL_BOOL(lp_readonly, bRead_only)
5349 FN_LOCAL_BOOL(lp_no_set_dir, bNo_set_dir)
5350 FN_LOCAL_BOOL(lp_guest_ok, bGuest_ok)
5351 FN_LOCAL_BOOL(lp_guest_only, bGuest_only)
5352 FN_LOCAL_BOOL(lp_administrative_share, bAdministrative_share)
5353 FN_LOCAL_BOOL(lp_print_ok, bPrint_ok)
5354 FN_LOCAL_BOOL(lp_map_hidden, bMap_hidden)
5355 FN_LOCAL_BOOL(lp_map_archive, bMap_archive)
5356 FN_LOCAL_BOOL(lp_store_dos_attributes, bStoreDosAttributes)
5357 FN_LOCAL_BOOL(lp_dmapi_support, bDmapiSupport)
5358 FN_LOCAL_PARM_BOOL(lp_locking, bLocking)
5359 FN_LOCAL_PARM_INTEGER(lp_strict_locking, iStrictLocking)
5360 FN_LOCAL_PARM_BOOL(lp_posix_locking, bPosixLocking)
5361 FN_LOCAL_BOOL(lp_share_modes, bShareModes)
5362 FN_LOCAL_BOOL(lp_oplocks, bOpLocks)
5363 FN_LOCAL_BOOL(lp_level2_oplocks, bLevel2OpLocks)
5364 FN_LOCAL_BOOL(lp_onlyuser, bOnlyUser)
5365 FN_LOCAL_PARM_BOOL(lp_manglednames, bMangledNames)
5366 FN_LOCAL_BOOL(lp_widelinks, bWidelinks)
5367 FN_LOCAL_BOOL(lp_symlinks, bSymlinks)
5368 FN_LOCAL_BOOL(lp_syncalways, bSyncAlways)
5369 FN_LOCAL_BOOL(lp_strict_allocate, bStrictAllocate)
5370 FN_LOCAL_BOOL(lp_strict_sync, bStrictSync)
5371 FN_LOCAL_BOOL(lp_map_system, bMap_system)
5372 FN_LOCAL_BOOL(lp_delete_readonly, bDeleteReadonly)
5373 FN_LOCAL_BOOL(lp_fake_oplocks, bFakeOplocks)
5374 FN_LOCAL_BOOL(lp_recursive_veto_delete, bDeleteVetoFiles)
5375 FN_LOCAL_BOOL(lp_dos_filemode, bDosFilemode)
5376 FN_LOCAL_BOOL(lp_dos_filetimes, bDosFiletimes)
5377 FN_LOCAL_BOOL(lp_dos_filetime_resolution, bDosFiletimeResolution)
5378 FN_LOCAL_BOOL(lp_fake_dir_create_times, bFakeDirCreateTimes)
5379 FN_LOCAL_BOOL(lp_blocking_locks, bBlockingLocks)
5380 FN_LOCAL_BOOL(lp_inherit_perms, bInheritPerms)
5381 FN_LOCAL_BOOL(lp_inherit_acls, bInheritACLS)
5382 FN_LOCAL_BOOL(lp_inherit_owner, bInheritOwner)
5383 FN_LOCAL_BOOL(lp_use_client_driver, bUseClientDriver)
5384 FN_LOCAL_BOOL(lp_default_devmode, bDefaultDevmode)
5385 FN_LOCAL_BOOL(lp_force_printername, bForcePrintername)
5386 FN_LOCAL_BOOL(lp_nt_acl_support, bNTAclSupport)
5387 FN_LOCAL_BOOL(lp_force_unknown_acl_user, bForceUnknownAclUser)
5388 FN_LOCAL_BOOL(lp_ea_support, bEASupport)
5389 FN_LOCAL_BOOL(_lp_use_sendfile, bUseSendfile)
5390 FN_LOCAL_BOOL(lp_profile_acls, bProfileAcls)
5391 FN_LOCAL_BOOL(lp_map_acl_inherit, bMap_acl_inherit)
5392 FN_LOCAL_BOOL(lp_afs_share, bAfs_Share)
5393 FN_LOCAL_BOOL(lp_acl_check_permissions, bAclCheckPermissions)
5394 FN_LOCAL_BOOL(lp_acl_group_control, bAclGroupControl)
5395 FN_LOCAL_BOOL(lp_acl_map_full_control, bAclMapFullControl)
5396 FN_LOCAL_INTEGER(lp_create_mask, iCreate_mask)
5397 FN_LOCAL_INTEGER(lp_force_create_mode, iCreate_force_mode)
5398 FN_LOCAL_INTEGER(lp_security_mask, iSecurity_mask)
5399 FN_LOCAL_INTEGER(lp_force_security_mode, iSecurity_force_mode)
5400 FN_LOCAL_INTEGER(lp_dir_mask, iDir_mask)
5401 FN_LOCAL_INTEGER(lp_force_dir_mode, iDir_force_mode)
5402 FN_LOCAL_INTEGER(lp_dir_security_mask, iDir_Security_mask)
5403 FN_LOCAL_INTEGER(lp_force_dir_security_mode, iDir_Security_force_mode)
5404 FN_LOCAL_INTEGER(lp_max_connections, iMaxConnections)
5405 FN_LOCAL_INTEGER(lp_defaultcase, iDefaultCase)
5406 FN_LOCAL_INTEGER(lp_minprintspace, iMinPrintSpace)
5407 FN_LOCAL_INTEGER(lp_printing, iPrinting)
5408 FN_LOCAL_INTEGER(lp_max_reported_jobs, iMaxReportedPrintJobs)
5409 FN_LOCAL_INTEGER(lp_oplock_contention_limit, iOplockContentionLimit)
5410 FN_LOCAL_INTEGER(lp_csc_policy, iCSCPolicy)
5411 FN_LOCAL_INTEGER(lp_write_cache_size, iWriteCacheSize)
5412 FN_LOCAL_INTEGER(lp_block_size, iBlock_size)
5413 FN_LOCAL_INTEGER(lp_dfree_cache_time, iDfreeCacheTime)
5414 FN_LOCAL_INTEGER(lp_allocation_roundup_size, iallocation_roundup_size)
5415 FN_LOCAL_INTEGER(lp_aio_read_size, iAioReadSize)
5416 FN_LOCAL_INTEGER(lp_aio_write_size, iAioWriteSize)
5417 FN_LOCAL_INTEGER(lp_map_readonly, iMap_readonly)
5418 FN_LOCAL_INTEGER(lp_directory_name_cache_size, iDirectoryNameCacheSize)
5419 FN_LOCAL_INTEGER(lp_smb_encrypt, ismb_encrypt)
5420 FN_LOCAL_CHAR(lp_magicchar, magic_char)
5421 FN_GLOBAL_INTEGER(lp_winbind_cache_time, &Globals.winbind_cache_time)
5422 FN_GLOBAL_INTEGER(lp_winbind_reconnect_delay, &Globals.winbind_reconnect_delay)
5423 FN_GLOBAL_LIST(lp_winbind_nss_info, &Globals.szWinbindNssInfo)
5424 FN_GLOBAL_INTEGER(lp_algorithmic_rid_base, &Globals.AlgorithmicRidBase)
5425 FN_GLOBAL_INTEGER(lp_name_cache_timeout, &Globals.name_cache_timeout)
5426 FN_GLOBAL_INTEGER(lp_client_signing, &Globals.client_signing)
5427 FN_GLOBAL_INTEGER(lp_server_signing, &Globals.server_signing)
5428 FN_GLOBAL_INTEGER(lp_client_ldap_sasl_wrapping, &Globals.client_ldap_sasl_wrapping)
5429
5430 /* local prototypes */
5431
5432 static int map_parameter(const char *pszParmName);
5433 static int map_parameter_canonical(const char *pszParmName, bool *inverse);
5434 static const char *get_boolean(bool bool_value);
5435 static int getservicebyname(const char *pszServiceName,
5436                             struct service *pserviceDest);
5437 static void copy_service(struct service *pserviceDest,
5438                          struct service *pserviceSource,
5439                          struct bitmap *pcopymapDest);
5440 static bool do_parameter(const char *pszParmName, const char *pszParmValue,
5441                          void *userdata);
5442 static bool do_section(const char *pszSectionName, void *userdata);
5443 static void init_copymap(struct service *pservice);
5444 static bool hash_a_service(const char *name, int number);
5445 static void free_service_byindex(int iService);
5446 static void free_param_opts(struct param_opt_struct **popts);
5447 static char * canonicalize_servicename(const char *name);
5448 static void show_parameter(int parmIndex);
5449 static bool is_synonym_of(int parm1, int parm2, bool *inverse);
5450
5451 /*
5452  * This is a helper function for parametrical options support.  It returns a
5453  * pointer to parametrical option value if it exists or NULL otherwise. Actual
5454  * parametrical functions are quite simple
5455  */
5456 static struct param_opt_struct *get_parametrics(int snum, const char *type,
5457                                                 const char *option)
5458 {
5459         bool global_section = False;
5460         char* param_key;
5461         struct param_opt_struct *data;
5462         
5463         if (snum >= iNumServices) return NULL;
5464         
5465         if (snum < 0) { 
5466                 data = Globals.param_opt;
5467                 global_section = True;
5468         } else {
5469                 data = ServicePtrs[snum]->param_opt;
5470         }
5471     
5472         if (asprintf(&param_key, "%s:%s", type, option) == -1) {
5473                 DEBUG(0,("asprintf failed!\n"));
5474                 return NULL;
5475         }
5476
5477         while (data) {
5478                 if (strwicmp(data->key, param_key) == 0) {
5479                         string_free(&param_key);
5480                         return data;
5481                 }
5482                 data = data->next;
5483         }
5484
5485         if (!global_section) {
5486                 /* Try to fetch the same option but from globals */
5487                 /* but only if we are not already working with Globals */
5488                 data = Globals.param_opt;
5489                 while (data) {
5490                         if (strwicmp(data->key, param_key) == 0) {
5491                                 string_free(&param_key);
5492                                 return data;
5493                         }
5494                         data = data->next;
5495                 }
5496         }
5497
5498         string_free(&param_key);
5499         
5500         return NULL;
5501 }
5502
5503
5504 #define MISSING_PARAMETER(name) \
5505     DEBUG(0, ("%s(): value is NULL or empty!\n", #name))
5506
5507 /*******************************************************************
5508 convenience routine to return int parameters.
5509 ********************************************************************/
5510 static int lp_int(const char *s)
5511 {
5512
5513         if (!s || !*s) {
5514                 MISSING_PARAMETER(lp_int);
5515                 return (-1);
5516         }
5517
5518         return (int)strtol(s, NULL, 0);
5519 }
5520
5521 /*******************************************************************
5522 convenience routine to return unsigned long parameters.
5523 ********************************************************************/
5524 static unsigned long lp_ulong(const char *s)
5525 {
5526
5527         if (!s || !*s) {
5528                 MISSING_PARAMETER(lp_ulong);
5529                 return (0);
5530         }
5531
5532         return strtoul(s, NULL, 0);
5533 }
5534
5535 /*******************************************************************
5536 convenience routine to return boolean parameters.
5537 ********************************************************************/
5538 static bool lp_bool(const char *s)
5539 {
5540         bool ret = False;
5541
5542         if (!s || !*s) {
5543                 MISSING_PARAMETER(lp_bool);
5544                 return False;
5545         }
5546         
5547         if (!set_boolean(s, &ret)) {
5548                 DEBUG(0,("lp_bool(%s): value is not boolean!\n",s));
5549                 return False;
5550         }
5551
5552         return ret;
5553 }
5554
5555 /*******************************************************************
5556 convenience routine to return enum parameters.
5557 ********************************************************************/
5558 static int lp_enum(const char *s,const struct enum_list *_enum)
5559 {
5560         int i;
5561
5562         if (!s || !*s || !_enum) {
5563                 MISSING_PARAMETER(lp_enum);
5564                 return (-1);
5565         }
5566         
5567         for (i=0; _enum[i].name; i++) {
5568                 if (strequal(_enum[i].name,s))
5569                         return _enum[i].value;
5570         }
5571
5572         DEBUG(0,("lp_enum(%s,enum): value is not in enum_list!\n",s));
5573         return (-1);
5574 }
5575
5576 #undef MISSING_PARAMETER
5577
5578 /* DO NOT USE lp_parm_string ANYMORE!!!!
5579  * use lp_parm_const_string or lp_parm_talloc_string
5580  *
5581  * lp_parm_string is only used to let old modules find this symbol
5582  */
5583 #undef lp_parm_string
5584  char *lp_parm_string(const char *servicename, const char *type, const char *option);
5585  char *lp_parm_string(const char *servicename, const char *type, const char *option)
5586 {
5587         return lp_parm_talloc_string(lp_servicenumber(servicename), type, option, NULL);
5588 }
5589
5590 /* Return parametric option from a given service. Type is a part of option before ':' */
5591 /* Parametric option has following syntax: 'Type: option = value' */
5592 /* the returned value is talloced on the talloc_tos() */
5593 char *lp_parm_talloc_string(int snum, const char *type, const char *option, const char *def)
5594 {
5595         struct param_opt_struct *data = get_parametrics(snum, type, option);
5596         
5597         if (data == NULL||data->value==NULL) {
5598                 if (def) {
5599                         return lp_string(def);
5600                 } else {
5601                         return NULL;
5602                 }
5603         }
5604
5605         return lp_string(data->value);
5606 }
5607
5608 /* Return parametric option from a given service. Type is a part of option before ':' */
5609 /* Parametric option has following syntax: 'Type: option = value' */
5610 const char *lp_parm_const_string(int snum, const char *type, const char *option, const char *def)
5611 {
5612         struct param_opt_struct *data = get_parametrics(snum, type, option);
5613         
5614         if (data == NULL||data->value==NULL)
5615                 return def;
5616                 
5617         return data->value;
5618 }
5619
5620 /* Return parametric option from a given service. Type is a part of option before ':' */
5621 /* Parametric option has following syntax: 'Type: option = value' */
5622
5623 const char **lp_parm_string_list(int snum, const char *type, const char *option, const char **def)
5624 {
5625         struct param_opt_struct *data = get_parametrics(snum, type, option);
5626
5627         if (data == NULL||data->value==NULL)
5628                 return (const char **)def;
5629                 
5630         if (data->list==NULL) {
5631                 data->list = str_list_make_v3(talloc_autofree_context(), data->value, NULL);
5632         }
5633
5634         return (const char **)data->list;
5635 }
5636
5637 /* Return parametric option from a given service. Type is a part of option before ':' */
5638 /* Parametric option has following syntax: 'Type: option = value' */
5639
5640 int lp_parm_int(int snum, const char *type, const char *option, int def)
5641 {
5642         struct param_opt_struct *data = get_parametrics(snum, type, option);
5643         
5644         if (data && data->value && *data->value)
5645                 return lp_int(data->value);
5646
5647         return def;
5648 }
5649
5650 /* Return parametric option from a given service. Type is a part of option before ':' */
5651 /* Parametric option has following syntax: 'Type: option = value' */
5652
5653 unsigned long lp_parm_ulong(int snum, const char *type, const char *option, unsigned long def)
5654 {
5655         struct param_opt_struct *data = get_parametrics(snum, type, option);
5656         
5657         if (data && data->value && *data->value)
5658                 return lp_ulong(data->value);
5659
5660         return def;
5661 }
5662
5663 /* Return parametric option from a given service. Type is a part of option before ':' */
5664 /* Parametric option has following syntax: 'Type: option = value' */
5665
5666 bool lp_parm_bool(int snum, const char *type, const char *option, bool def)
5667 {
5668         struct param_opt_struct *data = get_parametrics(snum, type, option);
5669         
5670         if (data && data->value && *data->value)
5671                 return lp_bool(data->value);
5672
5673         return def;
5674 }
5675
5676 /* Return parametric option from a given service. Type is a part of option before ':' */
5677 /* Parametric option has following syntax: 'Type: option = value' */
5678
5679 int lp_parm_enum(int snum, const char *type, const char *option,
5680                  const struct enum_list *_enum, int def)
5681 {
5682         struct param_opt_struct *data = get_parametrics(snum, type, option);
5683         
5684         if (data && data->value && *data->value && _enum)
5685                 return lp_enum(data->value, _enum);
5686
5687         return def;
5688 }
5689
5690
5691 /***************************************************************************
5692  Initialise a service to the defaults.
5693 ***************************************************************************/
5694
5695 static void init_service(struct service *pservice)
5696 {
5697         memset((char *)pservice, '\0', sizeof(struct service));
5698         copy_service(pservice, &sDefault, NULL);
5699 }
5700
5701
5702 /**
5703  * free a param_opts structure.
5704  * param_opts handling should be moved to talloc;
5705  * then this whole functions reduces to a TALLOC_FREE().
5706  */
5707
5708 static void free_param_opts(struct param_opt_struct **popts)
5709 {
5710         struct param_opt_struct *opt, *next_opt;
5711
5712         if (popts == NULL) {
5713                 return;
5714         }
5715
5716         if (*popts != NULL) {
5717                 DEBUG(5, ("Freeing parametrics:\n"));
5718         }
5719         opt = *popts;
5720         while (opt != NULL) {
5721                 string_free(&opt->key);
5722                 string_free(&opt->value);
5723                 TALLOC_FREE(opt->list);
5724                 next_opt = opt->next;
5725                 SAFE_FREE(opt);
5726                 opt = next_opt;
5727         }
5728         *popts = NULL;
5729 }
5730
5731 /***************************************************************************
5732  Free the dynamically allocated parts of a service struct.
5733 ***************************************************************************/
5734
5735 static void free_service(struct service *pservice)
5736 {
5737         if (!pservice)
5738                 return;
5739
5740         if (pservice->szService)
5741                 DEBUG(5, ("free_service: Freeing service %s\n",
5742                        pservice->szService));
5743
5744         free_parameters(getservicebyname(pservice->szService, NULL));
5745
5746         string_free(&pservice->szService);
5747         bitmap_free(pservice->copymap);
5748
5749         free_param_opts(&pservice->param_opt);
5750
5751         ZERO_STRUCTP(pservice);
5752 }
5753
5754
5755 /***************************************************************************
5756  remove a service indexed in the ServicePtrs array from the ServiceHash
5757  and free the dynamically allocated parts
5758 ***************************************************************************/
5759
5760 static void free_service_byindex(int idx)
5761 {
5762         if ( !LP_SNUM_OK(idx) ) 
5763                 return;
5764
5765         ServicePtrs[idx]->valid = False;
5766         invalid_services[num_invalid_services++] = idx;
5767
5768         /* we have to cleanup the hash record */
5769
5770         if (ServicePtrs[idx]->szService) {
5771                 char *canon_name = canonicalize_servicename(
5772                         ServicePtrs[idx]->szService );
5773                 
5774                 dbwrap_delete_bystring(ServiceHash, canon_name );
5775                 TALLOC_FREE(canon_name);
5776         }
5777
5778         free_service(ServicePtrs[idx]);
5779 }
5780
5781 /***************************************************************************
5782  Add a new service to the services array initialising it with the given 
5783  service. 
5784 ***************************************************************************/
5785
5786 static int add_a_service(const struct service *pservice, const char *name)
5787 {
5788         int i;
5789         struct service tservice;
5790         int num_to_alloc = iNumServices + 1;
5791
5792         tservice = *pservice;
5793
5794         /* it might already exist */
5795         if (name) {
5796                 i = getservicebyname(name, NULL);
5797                 if (i >= 0) {
5798                         /* Clean all parametric options for service */
5799                         /* They will be added during parsing again */
5800                         free_param_opts(&ServicePtrs[i]->param_opt);
5801                         return (i);
5802                 }
5803         }
5804
5805         /* find an invalid one */
5806         i = iNumServices;
5807         if (num_invalid_services > 0) {
5808                 i = invalid_services[--num_invalid_services];
5809         }
5810
5811         /* if not, then create one */
5812         if (i == iNumServices) {
5813                 struct service **tsp;
5814                 int *tinvalid;
5815                 
5816                 tsp = SMB_REALLOC_ARRAY_KEEP_OLD_ON_ERROR(ServicePtrs, struct service *, num_to_alloc);
5817                 if (tsp == NULL) {
5818                         DEBUG(0,("add_a_service: failed to enlarge ServicePtrs!\n"));
5819                         return (-1);
5820                 }
5821                 ServicePtrs = tsp;
5822                 ServicePtrs[iNumServices] = SMB_MALLOC_P(struct service);
5823                 if (!ServicePtrs[iNumServices]) {
5824                         DEBUG(0,("add_a_service: out of memory!\n"));
5825                         return (-1);
5826                 }
5827                 iNumServices++;
5828
5829                 /* enlarge invalid_services here for now... */
5830                 tinvalid = SMB_REALLOC_ARRAY_KEEP_OLD_ON_ERROR(invalid_services, int,
5831                                              num_to_alloc);
5832                 if (tinvalid == NULL) {
5833                         DEBUG(0,("add_a_service: failed to enlarge "
5834                                  "invalid_services!\n"));
5835                         return (-1);
5836                 }
5837                 invalid_services = tinvalid;
5838         } else {
5839                 free_service_byindex(i);
5840         }
5841
5842         ServicePtrs[i]->valid = True;
5843
5844         init_service(ServicePtrs[i]);
5845         copy_service(ServicePtrs[i], &tservice, NULL);
5846         if (name)
5847                 string_set(&ServicePtrs[i]->szService, name);
5848                 
5849         DEBUG(8,("add_a_service: Creating snum = %d for %s\n", 
5850                 i, ServicePtrs[i]->szService));
5851
5852         if (!hash_a_service(ServicePtrs[i]->szService, i)) {
5853                 return (-1);
5854         }
5855                 
5856         return (i);
5857 }
5858
5859 /***************************************************************************
5860   Convert a string to uppercase and remove whitespaces.
5861 ***************************************************************************/
5862
5863 static char *canonicalize_servicename(const char *src)
5864 {
5865         char *result;
5866
5867         if ( !src ) {
5868                 DEBUG(0,("canonicalize_servicename: NULL source name!\n"));
5869                 return NULL;
5870         }
5871
5872         result = talloc_strdup(talloc_tos(), src);
5873         SMB_ASSERT(result != NULL);
5874
5875         strlower_m(result);
5876         return result;
5877 }
5878
5879 /***************************************************************************
5880   Add a name/index pair for the services array to the hash table.
5881 ***************************************************************************/
5882
5883 static bool hash_a_service(const char *name, int idx)
5884 {
5885         char *canon_name;
5886
5887         if ( !ServiceHash ) {
5888                 DEBUG(10,("hash_a_service: creating servicehash\n"));
5889                 ServiceHash = db_open_rbt(NULL);
5890                 if ( !ServiceHash ) {
5891                         DEBUG(0,("hash_a_service: open tdb servicehash failed!\n"));
5892                         return False;
5893                 }
5894         }
5895
5896         DEBUG(10,("hash_a_service: hashing index %d for service name %s\n",
5897                 idx, name));
5898
5899         canon_name = canonicalize_servicename( name );
5900
5901         dbwrap_store_bystring(ServiceHash, canon_name,
5902                               make_tdb_data((uint8 *)&idx, sizeof(idx)),
5903                               TDB_REPLACE);
5904
5905         TALLOC_FREE(canon_name);
5906
5907         return True;
5908 }
5909
5910 /***************************************************************************
5911  Add a new home service, with the specified home directory, defaults coming
5912  from service ifrom.
5913 ***************************************************************************/
5914
5915 bool lp_add_home(const char *pszHomename, int iDefaultService,
5916                  const char *user, const char *pszHomedir)
5917 {
5918         int i;
5919
5920         i = add_a_service(ServicePtrs[iDefaultService], pszHomename);
5921
5922         if (i < 0)
5923                 return (False);
5924
5925         if (!(*(ServicePtrs[iDefaultService]->szPath))
5926             || strequal(ServicePtrs[iDefaultService]->szPath, lp_pathname(GLOBAL_SECTION_SNUM))) {
5927                 string_set(&ServicePtrs[i]->szPath, pszHomedir);
5928         }
5929
5930         if (!(*(ServicePtrs[i]->comment))) {
5931                 char *comment = NULL;
5932                 if (asprintf(&comment, "Home directory of %s", user) < 0) {
5933                         return false;
5934                 }
5935                 string_set(&ServicePtrs[i]->comment, comment);
5936                 SAFE_FREE(comment);
5937         }
5938
5939         /* set the browseable flag from the global default */
5940
5941         ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
5942         ServicePtrs[i]->bAccessBasedShareEnum = sDefault.bAccessBasedShareEnum;
5943
5944         ServicePtrs[i]->autoloaded = True;
5945
5946         DEBUG(3, ("adding home's share [%s] for user '%s' at '%s'\n", pszHomename, 
5947                user, ServicePtrs[i]->szPath ));
5948
5949         return (True);
5950 }
5951
5952 /***************************************************************************
5953  Add a new service, based on an old one.
5954 ***************************************************************************/
5955
5956 int lp_add_service(const char *pszService, int iDefaultService)
5957 {
5958         if (iDefaultService < 0) {
5959                 return add_a_service(&sDefault, pszService);
5960         }
5961
5962         return (add_a_service(ServicePtrs[iDefaultService], pszService));
5963 }
5964
5965 /***************************************************************************
5966  Add the IPC service.
5967 ***************************************************************************/
5968
5969 static bool lp_add_ipc(const char *ipc_name, bool guest_ok)
5970 {
5971         char *comment = NULL;
5972         int i = add_a_service(&sDefault, ipc_name);
5973
5974         if (i < 0)
5975                 return (False);
5976
5977         if (asprintf(&comment, "IPC Service (%s)",
5978                                 Globals.szServerString) < 0) {
5979                 return (False);
5980         }
5981
5982         string_set(&ServicePtrs[i]->szPath, tmpdir());
5983         string_set(&ServicePtrs[i]->szUsername, "");
5984         string_set(&ServicePtrs[i]->comment, comment);
5985         string_set(&ServicePtrs[i]->fstype, "IPC");
5986         ServicePtrs[i]->iMaxConnections = 0;
5987         ServicePtrs[i]->bAvailable = True;
5988         ServicePtrs[i]->bRead_only = True;
5989         ServicePtrs[i]->bGuest_only = False;
5990         ServicePtrs[i]->bAdministrative_share = True;
5991         ServicePtrs[i]->bGuest_ok = guest_ok;
5992         ServicePtrs[i]->bPrint_ok = False;
5993         ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
5994
5995         DEBUG(3, ("adding IPC service\n"));
5996
5997         SAFE_FREE(comment);
5998         return (True);
5999 }
6000
6001 /***************************************************************************
6002  Add a new printer service, with defaults coming from service iFrom.
6003 ***************************************************************************/
6004
6005 bool lp_add_printer(const char *pszPrintername, int iDefaultService)
6006 {
6007         const char *comment = "From Printcap";
6008         int i = add_a_service(ServicePtrs[iDefaultService], pszPrintername);
6009
6010         if (i < 0)
6011                 return (False);
6012
6013         /* note that we do NOT default the availability flag to True - */
6014         /* we take it from the default service passed. This allows all */
6015         /* dynamic printers to be disabled by disabling the [printers] */
6016         /* entry (if/when the 'available' keyword is implemented!).    */
6017
6018         /* the printer name is set to the service name. */
6019         string_set(&ServicePtrs[i]->szPrintername, pszPrintername);
6020         string_set(&ServicePtrs[i]->comment, comment);
6021
6022         /* set the browseable flag from the gloabl default */
6023         ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
6024
6025         /* Printers cannot be read_only. */
6026         ServicePtrs[i]->bRead_only = False;
6027         /* No share modes on printer services. */
6028         ServicePtrs[i]->bShareModes = False;
6029         /* No oplocks on printer services. */
6030         ServicePtrs[i]->bOpLocks = False;
6031         /* Printer services must be printable. */
6032         ServicePtrs[i]->bPrint_ok = True;
6033         
6034         DEBUG(3, ("adding printer service %s\n", pszPrintername));
6035
6036         return (True);
6037 }
6038
6039
6040 /***************************************************************************
6041  Check whether the given parameter name is valid.
6042  Parametric options (names containing a colon) are considered valid.
6043 ***************************************************************************/
6044
6045 bool lp_parameter_is_valid(const char *pszParmName)
6046 {
6047         return ((map_parameter(pszParmName) != -1) ||
6048                 (strchr(pszParmName, ':') != NULL));
6049 }
6050
6051 /***************************************************************************
6052  Check whether the given name is the name of a global parameter.
6053  Returns True for strings belonging to parameters of class
6054  P_GLOBAL, False for all other strings, also for parametric options
6055  and strings not belonging to any option.
6056 ***************************************************************************/
6057
6058 bool lp_parameter_is_global(const char *pszParmName)
6059 {
6060         int num = map_parameter(pszParmName);
6061
6062         if (num >= 0) {
6063                 return (parm_table[num].p_class == P_GLOBAL);
6064         }
6065
6066         return False;
6067 }
6068
6069 /**************************************************************************
6070  Check whether the given name is the canonical name of a parameter.
6071  Returns False if it is not a valid parameter Name.
6072  For parametric options, True is returned.
6073 **************************************************************************/
6074
6075 bool lp_parameter_is_canonical(const char *parm_name)
6076 {
6077         if (!lp_parameter_is_valid(parm_name)) {
6078                 return False;
6079         }
6080
6081         return (map_parameter(parm_name) ==
6082                 map_parameter_canonical(parm_name, NULL));
6083 }
6084
6085 /**************************************************************************
6086  Determine the canonical name for a parameter.
6087  Indicate when it is an inverse (boolean) synonym instead of a
6088  "usual" synonym.
6089 **************************************************************************/
6090
6091 bool lp_canonicalize_parameter(const char *parm_name, const char **canon_parm,
6092                                bool *inverse)
6093 {
6094         int num;
6095
6096         if (!lp_parameter_is_valid(parm_name)) {
6097                 *canon_parm = NULL;
6098                 return False;
6099         }
6100
6101         num = map_parameter_canonical(parm_name, inverse);
6102         if (num < 0) {
6103                 /* parametric option */
6104                 *canon_parm = parm_name;
6105         } else {
6106                 *canon_parm = parm_table[num].label;
6107         }
6108
6109         return True;
6110
6111 }
6112
6113 /**************************************************************************
6114  Determine the canonical name for a parameter.
6115  Turn the value given into the inverse boolean expression when
6116  the synonym is an invers boolean synonym.
6117
6118  Return True if parm_name is a valid parameter name and
6119  in case it is an invers boolean synonym, if the val string could
6120  successfully be converted to the reverse bool.
6121  Return false in all other cases.
6122 **************************************************************************/
6123
6124 bool lp_canonicalize_parameter_with_value(const char *parm_name,
6125                                           const char *val,
6126                                           const char **canon_parm,
6127                                           const char **canon_val)
6128 {
6129         int num;
6130         bool inverse;
6131
6132         if (!lp_parameter_is_valid(parm_name)) {
6133                 *canon_parm = NULL;
6134                 *canon_val = NULL;
6135                 return False;
6136         }
6137
6138         num = map_parameter_canonical(parm_name, &inverse);
6139         if (num < 0) {
6140                 /* parametric option */
6141                 *canon_parm = parm_name;
6142                 *canon_val = val;
6143         } else {
6144                 *canon_parm = parm_table[num].label;
6145                 if (inverse) {
6146                         if (!lp_invert_boolean(val, canon_val)) {
6147                                 *canon_val = NULL;
6148                                 return False;
6149                         }
6150                 } else {
6151                         *canon_val = val;
6152                 }
6153         }
6154
6155         return True;
6156 }
6157
6158 /***************************************************************************
6159  Map a parameter's string representation to something we can use. 
6160  Returns False if the parameter string is not recognised, else TRUE.
6161 ***************************************************************************/
6162
6163 static int map_parameter(const char *pszParmName)
6164 {
6165         int iIndex;
6166
6167         if (*pszParmName == '-' && !strequal(pszParmName, "-valid"))
6168                 return (-1);
6169
6170         for (iIndex = 0; parm_table[iIndex].label; iIndex++)
6171                 if (strwicmp(parm_table[iIndex].label, pszParmName) == 0)
6172                         return (iIndex);
6173
6174         /* Warn only if it isn't parametric option */
6175         if (strchr(pszParmName, ':') == NULL)
6176                 DEBUG(1, ("Unknown parameter encountered: \"%s\"\n", pszParmName));
6177         /* We do return 'fail' for parametric options as well because they are
6178            stored in different storage
6179          */
6180         return (-1);
6181 }
6182
6183 /***************************************************************************
6184  Map a parameter's string representation to the index of the canonical
6185  form of the parameter (it might be a synonym).
6186  Returns -1 if the parameter string is not recognised.
6187 ***************************************************************************/
6188
6189 static int map_parameter_canonical(const char *pszParmName, bool *inverse)
6190 {
6191         int parm_num, canon_num;
6192         bool loc_inverse = False;
6193
6194         parm_num = map_parameter(pszParmName);
6195         if ((parm_num < 0) || !(parm_table[parm_num].flags & FLAG_HIDE)) {
6196                 /* invalid, parametric or no canidate for synonyms ... */
6197                 goto done;
6198         }
6199
6200         for (canon_num = 0; parm_table[canon_num].label; canon_num++) {
6201                 if (is_synonym_of(parm_num, canon_num, &loc_inverse)) {
6202                         parm_num = canon_num;
6203                         goto done;
6204                 }
6205         }
6206
6207 done:
6208         if (inverse != NULL) {
6209                 *inverse = loc_inverse;
6210         }
6211         return parm_num;
6212 }
6213
6214 /***************************************************************************
6215  return true if parameter number parm1 is a synonym of parameter
6216  number parm2 (parm2 being the principal name).
6217  set inverse to True if parm1 is P_BOOLREV and parm2 is P_BOOL,
6218  False otherwise.
6219 ***************************************************************************/
6220
6221 static bool is_synonym_of(int parm1, int parm2, bool *inverse)
6222 {
6223         if ((parm_table[parm1].ptr == parm_table[parm2].ptr) &&
6224             (parm_table[parm1].flags & FLAG_HIDE) &&
6225             !(parm_table[parm2].flags & FLAG_HIDE))
6226         {
6227                 if (inverse != NULL) {
6228                         if ((parm_table[parm1].type == P_BOOLREV) &&
6229                             (parm_table[parm2].type == P_BOOL))
6230                         {
6231                                 *inverse = True;
6232                         } else {
6233                                 *inverse = False;
6234                         }
6235                 }
6236                 return True;
6237         }
6238         return False;
6239 }
6240
6241 /***************************************************************************
6242  Show one parameter's name, type, [values,] and flags.
6243  (helper functions for show_parameter_list)
6244 ***************************************************************************/
6245
6246 static void show_parameter(int parmIndex)
6247 {
6248         int enumIndex, flagIndex;
6249         int parmIndex2;
6250         bool hadFlag;
6251         bool hadSyn;
6252         bool inverse;
6253         const char *type[] = { "P_BOOL", "P_BOOLREV", "P_CHAR", "P_INTEGER",
6254                 "P_OCTAL", "P_LIST", "P_STRING", "P_USTRING",
6255                 "P_ENUM", "P_SEP"};
6256         unsigned flags[] = { FLAG_BASIC, FLAG_SHARE, FLAG_PRINT, FLAG_GLOBAL,
6257                 FLAG_WIZARD, FLAG_ADVANCED, FLAG_DEVELOPER, FLAG_DEPRECATED,
6258                 FLAG_HIDE, FLAG_DOS_STRING};
6259         const char *flag_names[] = { "FLAG_BASIC", "FLAG_SHARE", "FLAG_PRINT",
6260                 "FLAG_GLOBAL", "FLAG_WIZARD", "FLAG_ADVANCED", "FLAG_DEVELOPER",
6261                 "FLAG_DEPRECATED", "FLAG_HIDE", "FLAG_DOS_STRING", NULL};
6262
6263         printf("%s=%s", parm_table[parmIndex].label,
6264                type[parm_table[parmIndex].type]);
6265         if (parm_table[parmIndex].type == P_ENUM) {
6266                 printf(",");
6267                 for (enumIndex=0;
6268                      parm_table[parmIndex].enum_list[enumIndex].name;
6269                      enumIndex++)
6270                 {
6271                         printf("%s%s",
6272                                enumIndex ? "|" : "",
6273                                parm_table[parmIndex].enum_list[enumIndex].name);
6274                 }
6275         }
6276         printf(",");
6277         hadFlag = False;
6278         for (flagIndex=0; flag_names[flagIndex]; flagIndex++) {
6279                 if (parm_table[parmIndex].flags & flags[flagIndex]) {
6280                         printf("%s%s",
6281                                 hadFlag ? "|" : "",
6282                                 flag_names[flagIndex]);
6283                         hadFlag = True;
6284                 }
6285         }
6286
6287         /* output synonyms */
6288         hadSyn = False;
6289         for (parmIndex2=0; parm_table[parmIndex2].label; parmIndex2++) {
6290                 if (is_synonym_of(parmIndex, parmIndex2, &inverse)) {
6291                         printf(" (%ssynonym of %s)", inverse ? "inverse " : "",
6292                                parm_table[parmIndex2].label);
6293                 } else if (is_synonym_of(parmIndex2, parmIndex, &inverse)) {
6294                         if (!hadSyn) {
6295                                 printf(" (synonyms: ");
6296                                 hadSyn = True;
6297                         } else {
6298                                 printf(", ");
6299                         }
6300                         printf("%s%s", parm_table[parmIndex2].label,
6301                                inverse ? "[i]" : "");
6302                 }
6303         }
6304         if (hadSyn) {
6305                 printf(")");
6306         }
6307
6308         printf("\n");
6309 }
6310
6311 /***************************************************************************
6312  Show all parameter's name, type, [values,] and flags.
6313 ***************************************************************************/
6314
6315 void show_parameter_list(void)
6316 {
6317         int classIndex, parmIndex;
6318         const char *section_names[] = { "local", "global", NULL};
6319
6320         for (classIndex=0; section_names[classIndex]; classIndex++) {
6321                 printf("[%s]\n", section_names[classIndex]);
6322                 for (parmIndex = 0; parm_table[parmIndex].label; parmIndex++) {
6323                         if (parm_table[parmIndex].p_class == classIndex) {
6324                                 show_parameter(parmIndex);
6325                         }
6326                 }
6327         }
6328 }
6329
6330 /***************************************************************************
6331  Check if a given string correctly represents a boolean value.
6332 ***************************************************************************/
6333
6334 bool lp_string_is_valid_boolean(const char *parm_value)
6335 {
6336         return set_boolean(parm_value, NULL);
6337 }
6338
6339 /***************************************************************************
6340  Get the standard string representation of a boolean value ("yes" or "no")
6341 ***************************************************************************/
6342
6343 static const char *get_boolean(bool bool_value)
6344 {
6345         static const char *yes_str = "yes";
6346         static const char *no_str = "no";
6347
6348         return (bool_value ? yes_str : no_str);
6349 }
6350
6351 /***************************************************************************
6352  Provide the string of the negated boolean value associated to the boolean
6353  given as a string. Returns False if the passed string does not correctly
6354  represent a boolean.
6355 ***************************************************************************/
6356
6357 bool lp_invert_boolean(const char *str, const char **inverse_str)
6358 {
6359         bool val;
6360
6361         if (!set_boolean(str, &val)) {
6362                 return False;
6363         }
6364
6365         *inverse_str = get_boolean(!val);
6366         return True;
6367 }
6368
6369 /***************************************************************************
6370  Provide the canonical string representation of a boolean value given
6371  as a string. Return True on success, False if the string given does
6372  not correctly represent a boolean.
6373 ***************************************************************************/
6374
6375 bool lp_canonicalize_boolean(const char *str, const char**canon_str)
6376 {
6377         bool val;
6378
6379         if (!set_boolean(str, &val)) {
6380                 return False;
6381         }
6382
6383         *canon_str = get_boolean(val);
6384         return True;
6385 }
6386
6387 /***************************************************************************
6388 Find a service by name. Otherwise works like get_service.
6389 ***************************************************************************/
6390
6391 static int getservicebyname(const char *pszServiceName, struct service *pserviceDest)
6392 {
6393         int iService = -1;
6394         char *canon_name;
6395         TDB_DATA data;
6396
6397         if (ServiceHash == NULL) {
6398                 return -1;
6399         }
6400
6401         canon_name = canonicalize_servicename(pszServiceName);
6402
6403         data = dbwrap_fetch_bystring(ServiceHash, canon_name, canon_name);
6404
6405         if ((data.dptr != NULL) && (data.dsize == sizeof(iService))) {
6406                 iService = *(int *)data.dptr;
6407         }
6408
6409         TALLOC_FREE(canon_name);
6410
6411         if ((iService != -1) && (LP_SNUM_OK(iService))
6412             && (pserviceDest != NULL)) {
6413                 copy_service(pserviceDest, ServicePtrs[iService], NULL);
6414         }
6415
6416         return (iService);
6417 }
6418
6419 /***************************************************************************
6420  Copy a service structure to another.
6421  If pcopymapDest is NULL then copy all fields
6422 ***************************************************************************/
6423
6424 /**
6425  * Add a parametric option to a param_opt_struct,
6426  * replacing old value, if already present.
6427  */
6428 static void set_param_opt(struct param_opt_struct **opt_list,
6429                           const char *opt_name,
6430                           const char *opt_value)
6431 {
6432         struct param_opt_struct *new_opt, *opt;
6433         bool not_added;
6434
6435         if (opt_list == NULL) {
6436                 return;
6437         }
6438
6439         opt = *opt_list;
6440         not_added = true;
6441
6442         /* Traverse destination */
6443         while (opt) {
6444                 /* If we already have same option, override it */
6445                 if (strwicmp(opt->key, opt_name) == 0) {
6446                         string_free(&opt->value);
6447                         TALLOC_FREE(opt->list);
6448                         opt->value = SMB_STRDUP(opt_value);
6449                         not_added = false;
6450                         break;
6451                 }
6452                 opt = opt->next;
6453         }
6454         if (not_added) {
6455             new_opt = SMB_XMALLOC_P(struct param_opt_struct);
6456             new_opt->key = SMB_STRDUP(opt_name);
6457             new_opt->value = SMB_STRDUP(opt_value);
6458             new_opt->list = NULL;
6459             DLIST_ADD(*opt_list, new_opt);
6460         }
6461 }
6462
6463 static void copy_service(struct service *pserviceDest, struct service *pserviceSource,
6464                          struct bitmap *pcopymapDest)
6465 {
6466         int i;
6467         bool bcopyall = (pcopymapDest == NULL);
6468         struct param_opt_struct *data;
6469
6470         for (i = 0; parm_table[i].label; i++)
6471                 if (parm_table[i].ptr && parm_table[i].p_class == P_LOCAL &&
6472                     (bcopyall || bitmap_query(pcopymapDest,i))) {
6473                         void *def_ptr = parm_table[i].ptr;
6474                         void *src_ptr =
6475                                 ((char *)pserviceSource) + PTR_DIFF(def_ptr,
6476                                                                     &sDefault);
6477                         void *dest_ptr =
6478                                 ((char *)pserviceDest) + PTR_DIFF(def_ptr,
6479                                                                   &sDefault);
6480
6481                         switch (parm_table[i].type) {
6482                                 case P_BOOL:
6483                                 case P_BOOLREV:
6484                                         *(bool *)dest_ptr = *(bool *)src_ptr;
6485                                         break;
6486
6487                                 case P_INTEGER:
6488                                 case P_ENUM:
6489                                 case P_OCTAL:
6490                                         *(int *)dest_ptr = *(int *)src_ptr;
6491                                         break;
6492
6493                                 case P_CHAR:
6494                                         *(char *)dest_ptr = *(char *)src_ptr;
6495                                         break;
6496
6497                                 case P_STRING:
6498                                         string_set((char **)dest_ptr,
6499                                                    *(char **)src_ptr);
6500                                         break;
6501
6502                                 case P_USTRING:
6503                                         string_set((char **)dest_ptr,
6504                                                    *(char **)src_ptr);
6505                                         strupper_m(*(char **)dest_ptr);
6506                                         break;
6507                                 case P_LIST:
6508                                         TALLOC_FREE(*((char ***)dest_ptr));
6509                                         *((char ***)dest_ptr) = str_list_copy(NULL, 
6510                                                       *(const char ***)src_ptr);
6511                                         break;
6512                                 default:
6513                                         break;
6514                         }
6515                 }
6516
6517         if (bcopyall) {
6518                 init_copymap(pserviceDest);
6519                 if (pserviceSource->copymap)
6520                         bitmap_copy(pserviceDest->copymap,
6521                                     pserviceSource->copymap);
6522         }
6523         
6524         data = pserviceSource->param_opt;
6525         while (data) {
6526                 set_param_opt(&pserviceDest->param_opt, data->key, data->value);
6527                 data = data->next;
6528         }
6529 }
6530
6531 /***************************************************************************
6532 Check a service for consistency. Return False if the service is in any way
6533 incomplete or faulty, else True.
6534 ***************************************************************************/
6535
6536 bool service_ok(int iService)
6537 {
6538         bool bRetval;
6539
6540         bRetval = True;
6541         if (ServicePtrs[iService]->szService[0] == '\0') {
6542                 DEBUG(0, ("The following message indicates an internal error:\n"));
6543                 DEBUG(0, ("No service name in service entry.\n"));
6544                 bRetval = False;
6545         }
6546
6547         /* The [printers] entry MUST be printable. I'm all for flexibility, but */
6548         /* I can't see why you'd want a non-printable printer service...        */
6549         if (strwicmp(ServicePtrs[iService]->szService, PRINTERS_NAME) == 0) {
6550                 if (!ServicePtrs[iService]->bPrint_ok) {
6551                         DEBUG(0, ("WARNING: [%s] service MUST be printable!\n",
6552                                ServicePtrs[iService]->szService));
6553                         ServicePtrs[iService]->bPrint_ok = True;
6554                 }
6555                 /* [printers] service must also be non-browsable. */
6556                 if (ServicePtrs[iService]->bBrowseable)
6557                         ServicePtrs[iService]->bBrowseable = False;
6558         }
6559
6560         if (ServicePtrs[iService]->szPath[0] == '\0' &&
6561             strwicmp(ServicePtrs[iService]->szService, HOMES_NAME) != 0 &&
6562             ServicePtrs[iService]->szMSDfsProxy[0] == '\0'
6563             ) {
6564                 DEBUG(0, ("WARNING: No path in service %s - making it unavailable!\n",
6565                         ServicePtrs[iService]->szService));
6566                 ServicePtrs[iService]->bAvailable = False;
6567         }
6568
6569         /* If a service is flagged unavailable, log the fact at level 1. */
6570         if (!ServicePtrs[iService]->bAvailable)
6571                 DEBUG(1, ("NOTE: Service %s is flagged unavailable.\n",
6572                           ServicePtrs[iService]->szService));
6573
6574         return (bRetval);
6575 }
6576
6577 static struct smbconf_ctx *lp_smbconf_ctx(void)
6578 {
6579         WERROR werr;
6580         static struct smbconf_ctx *conf_ctx = NULL;
6581
6582         if (conf_ctx == NULL) {
6583                 werr = smbconf_init(NULL, &conf_ctx, "registry:");
6584                 if (!W_ERROR_IS_OK(werr)) {
6585                         DEBUG(1, ("error initializing registry configuration: "
6586                                   "%s\n", win_errstr(werr)));
6587                         conf_ctx = NULL;
6588                 }
6589         }
6590
6591         return conf_ctx;
6592 }
6593
6594 static bool process_smbconf_service(struct smbconf_service *service)
6595 {
6596         uint32_t count;
6597         bool ret;
6598
6599         if (service == NULL) {
6600                 return false;
6601         }
6602
6603         ret = do_section(service->name, NULL);
6604         if (ret != true) {
6605                 return false;
6606         }
6607         for (count = 0; count < service->num_params; count++) {
6608                 ret = do_parameter(service->param_names[count],
6609                                    service->param_values[count],
6610                                    NULL);
6611                 if (ret != true) {
6612                         return false;
6613                 }
6614         }
6615         return true;
6616 }
6617
6618 /*
6619  * process_registry_globals
6620  */
6621 static bool process_registry_globals(void)
6622 {
6623         WERROR werr;
6624         struct smbconf_service *service = NULL;
6625         TALLOC_CTX *mem_ctx = talloc_stackframe();
6626         struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
6627         bool ret = false;
6628
6629         if (conf_ctx == NULL) {
6630                 goto done;
6631         }
6632
6633         ret = do_parameter("registry shares", "yes", NULL);
6634         if (!ret) {
6635                 goto done;
6636         }
6637
6638         if (!smbconf_share_exists(conf_ctx, GLOBAL_NAME)) {
6639                 /* nothing to read from the registry yet but make sure lp_load
6640                  * doesn't return false */
6641                 ret = true;
6642                 goto done;
6643         }
6644
6645         werr = smbconf_get_share(conf_ctx, mem_ctx, GLOBAL_NAME, &service);
6646         if (!W_ERROR_IS_OK(werr)) {
6647                 goto done;
6648         }
6649
6650         ret = process_smbconf_service(service);
6651         if (!ret) {
6652                 goto done;
6653         }
6654
6655         /* store the csn */
6656         smbconf_changed(conf_ctx, &conf_last_csn, NULL, NULL);
6657
6658 done:
6659         TALLOC_FREE(mem_ctx);
6660         return ret;
6661 }
6662
6663 static bool process_registry_shares(void)
6664 {
6665         WERROR werr;
6666         uint32_t count;
6667         struct smbconf_service **service = NULL;
6668         uint32_t num_shares = 0;
6669         TALLOC_CTX *mem_ctx = talloc_stackframe();
6670         struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
6671         bool ret = false;
6672
6673         if (conf_ctx == NULL) {
6674                 goto done;
6675         }
6676
6677         werr = smbconf_get_config(conf_ctx, mem_ctx, &num_shares, &service);
6678         if (!W_ERROR_IS_OK(werr)) {
6679                 goto done;
6680         }
6681
6682         ret = true;
6683
6684         for (count = 0; count < num_shares; count++) {
6685                 if (strequal(service[count]->name, GLOBAL_NAME)) {
6686                         continue;
6687                 }
6688                 ret = process_smbconf_service(service[count]);
6689                 if (!ret) {
6690                         goto done;
6691                 }
6692         }
6693
6694         /* store the csn */
6695         smbconf_changed(conf_ctx, &conf_last_csn, NULL, NULL);
6696
6697 done:
6698         TALLOC_FREE(mem_ctx);
6699         return ret;
6700 }
6701
6702 static struct file_lists {
6703         struct file_lists *next;
6704         char *name;
6705         char *subfname;
6706         time_t modtime;
6707 } *file_lists = NULL;
6708
6709 /*******************************************************************
6710  Keep a linked list of all config files so we know when one has changed 
6711  it's date and needs to be reloaded.
6712 ********************************************************************/
6713
6714 static void add_to_file_list(const char *fname, const char *subfname)
6715 {
6716         struct file_lists *f = file_lists;
6717
6718         while (f) {
6719                 if (f->name && !strcmp(f->name, fname))
6720                         break;
6721                 f = f->next;
6722         }
6723
6724         if (!f) {
6725                 f = SMB_MALLOC_P(struct file_lists);
6726                 if (!f)
6727                         return;
6728                 f->next = file_lists;
6729                 f->name = SMB_STRDUP(fname);
6730                 if (!f->name) {
6731                         SAFE_FREE(f);
6732                         return;
6733                 }
6734                 f->subfname = SMB_STRDUP(subfname);
6735                 if (!f->subfname) {
6736                         SAFE_FREE(f);
6737                         return;
6738                 }
6739                 file_lists = f;
6740                 f->modtime = file_modtime(subfname);
6741         } else {
6742                 time_t t = file_modtime(subfname);
6743                 if (t)
6744                         f->modtime = t;
6745         }
6746 }
6747
6748 /**
6749  * Utility function for outsiders to check if we're running on registry.
6750  */
6751 bool lp_config_backend_is_registry(void)
6752 {
6753         return (lp_config_backend() == CONFIG_BACKEND_REGISTRY);
6754 }
6755
6756 /**
6757  * Utility function to check if the config backend is FILE.
6758  */
6759 bool lp_config_backend_is_file(void)
6760 {
6761         return (lp_config_backend() == CONFIG_BACKEND_FILE);
6762 }
6763
6764 /*******************************************************************
6765  Check if a config file has changed date.
6766 ********************************************************************/
6767
6768 bool lp_file_list_changed(void)
6769 {
6770         struct file_lists *f = file_lists;
6771
6772         DEBUG(6, ("lp_file_list_changed()\n"));
6773
6774         if (lp_config_backend_is_registry()) {
6775                 struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
6776
6777                 if (conf_ctx == NULL) {
6778                         return false;
6779                 }
6780                 if (smbconf_changed(conf_ctx, &conf_last_csn, NULL, NULL)) {
6781                         DEBUGADD(6, ("registry config changed\n"));
6782                         return true;
6783                 }
6784         }
6785
6786         while (f) {
6787                 char *n2 = NULL;
6788                 time_t mod_time;
6789
6790                 n2 = alloc_sub_basic(get_current_username(),
6791                                     current_user_info.domain,
6792                                     f->name);
6793                 if (!n2) {
6794                         return false;
6795                 }
6796                 DEBUGADD(6, ("file %s -> %s  last mod_time: %s\n",
6797                              f->name, n2, ctime(&f->modtime)));
6798
6799                 mod_time = file_modtime(n2);
6800
6801                 if (mod_time && ((f->modtime != mod_time) || (f->subfname == NULL) || (strcmp(n2, f->subfname) != 0))) {
6802                         DEBUGADD(6,
6803                                  ("file %s modified: %s\n", n2,
6804                                   ctime(&mod_time)));
6805                         f->modtime = mod_time;
6806                         SAFE_FREE(f->subfname);
6807                         f->subfname = n2; /* Passing ownership of
6808                                              return from alloc_sub_basic
6809                                              above. */
6810                         return true;
6811                 }
6812                 SAFE_FREE(n2);
6813                 f = f->next;
6814         }
6815         return (False);
6816 }
6817
6818
6819 /***************************************************************************
6820  Run standard_sub_basic on netbios name... needed because global_myname
6821  is not accessed through any lp_ macro.
6822  Note: We must *NOT* use string_set() here as ptr points to global_myname.
6823 ***************************************************************************/
6824
6825 static bool handle_netbios_name(int snum, const char *pszParmValue, char **ptr)
6826 {
6827         bool ret;
6828         char *netbios_name = alloc_sub_basic(get_current_username(),
6829                                         current_user_info.domain,
6830                                         pszParmValue);
6831
6832         ret = set_global_myname(netbios_name);
6833         SAFE_FREE(netbios_name);
6834         string_set(&Globals.szNetbiosName,global_myname());
6835
6836         DEBUG(4, ("handle_netbios_name: set global_myname to: %s\n",
6837                global_myname()));
6838
6839         return ret;
6840 }
6841
6842 static bool handle_charset(int snum, const char *pszParmValue, char **ptr)
6843 {
6844         if (strcmp(*ptr, pszParmValue) != 0) {
6845                 string_set(ptr, pszParmValue);
6846                 init_iconv();
6847         }
6848         return True;
6849 }
6850
6851
6852
6853 static bool handle_workgroup(int snum, const char *pszParmValue, char **ptr)
6854 {
6855         bool ret;
6856         
6857         ret = set_global_myworkgroup(pszParmValue);
6858         string_set(&Globals.szWorkgroup,lp_workgroup());
6859         
6860         return ret;
6861 }
6862
6863 static bool handle_netbios_scope(int snum, const char *pszParmValue, char **ptr)
6864 {
6865         bool ret;
6866         
6867         ret = set_global_scope(pszParmValue);
6868         string_set(&Globals.szNetbiosScope,global_scope());
6869
6870         return ret;
6871 }
6872
6873 static bool handle_netbios_aliases(int snum, const char *pszParmValue, char **ptr)
6874 {
6875         TALLOC_FREE(Globals.szNetbiosAliases);
6876         Globals.szNetbiosAliases = str_list_make_v3(talloc_autofree_context(), pszParmValue, NULL);
6877         return set_netbios_aliases((const char **)Globals.szNetbiosAliases);
6878 }
6879
6880 /***************************************************************************
6881  Handle the include operation.
6882 ***************************************************************************/
6883 static bool bAllowIncludeRegistry = true;
6884
6885 static bool handle_include(int snum, const char *pszParmValue, char **ptr)
6886 {
6887         char *fname;
6888
6889         if (strequal(pszParmValue, INCLUDE_REGISTRY_NAME)) {
6890                 if (!bAllowIncludeRegistry) {
6891                         return true;
6892                 }
6893                 if (bInGlobalSection) {
6894                         return process_registry_globals();
6895                 } else {
6896                         DEBUG(1, ("\"include = registry\" only effective "
6897                                   "in %s section\n", GLOBAL_NAME));
6898                         return false;
6899                 }
6900         }
6901
6902         fname = alloc_sub_basic(get_current_username(),
6903                                 current_user_info.domain,
6904                                 pszParmValue);
6905
6906         add_to_file_list(pszParmValue, fname);
6907
6908         string_set(ptr, fname);
6909
6910         if (file_exist(fname)) {
6911                 bool ret = pm_process(fname, do_section, do_parameter, NULL);
6912                 SAFE_FREE(fname);
6913                 return ret;
6914         }
6915
6916         DEBUG(2, ("Can't find include file %s\n", fname));
6917         SAFE_FREE(fname);
6918         return true;
6919 }
6920
6921 /***************************************************************************
6922  Handle the interpretation of the copy parameter.
6923 ***************************************************************************/
6924
6925 static bool handle_copy(int snum, const char *pszParmValue, char **ptr)
6926 {
6927         bool bRetval;
6928         int iTemp;
6929         struct service serviceTemp;
6930
6931         string_set(ptr, pszParmValue);
6932
6933         init_service(&serviceTemp);
6934
6935         bRetval = False;
6936
6937         DEBUG(3, ("Copying service from service %s\n", pszParmValue));
6938
6939         if ((iTemp = getservicebyname(pszParmValue, &serviceTemp)) >= 0) {
6940                 if (iTemp == iServiceIndex) {
6941                         DEBUG(0, ("Can't copy service %s - unable to copy self!\n", pszParmValue));
6942                 } else {
6943                         copy_service(ServicePtrs[iServiceIndex],
6944                                      &serviceTemp,
6945                                      ServicePtrs[iServiceIndex]->copymap);
6946                         bRetval = True;
6947                 }
6948         } else {
6949                 DEBUG(0, ("Unable to copy service - source not found: %s\n", pszParmValue));
6950                 bRetval = False;
6951         }
6952
6953         free_service(&serviceTemp);
6954         return (bRetval);
6955 }
6956
6957 static bool handle_ldap_debug_level(int snum, const char *pszParmValue, char **ptr)
6958 {
6959         Globals.ldap_debug_level = lp_int(pszParmValue);
6960         init_ldap_debugging();
6961         return true;
6962 }
6963
6964 /***************************************************************************
6965  Handle idmap/non unix account uid and gid allocation parameters.  The format of these
6966  parameters is:
6967
6968  [global]
6969
6970         idmap uid = 1000-1999
6971         idmap gid = 700-899
6972
6973  We only do simple parsing checks here.  The strings are parsed into useful
6974  structures in the idmap daemon code.
6975
6976 ***************************************************************************/
6977
6978 /* Some lp_ routines to return idmap [ug]id information */
6979
6980 static uid_t idmap_uid_low, idmap_uid_high;
6981 static gid_t idmap_gid_low, idmap_gid_high;
6982
6983 bool lp_idmap_uid(uid_t *low, uid_t *high)
6984 {
6985         if (idmap_uid_low == 0 || idmap_uid_high == 0)
6986                 return False;
6987
6988         if (low)
6989                 *low = idmap_uid_low;
6990
6991         if (high)
6992                 *high = idmap_uid_high;
6993
6994         return True;
6995 }
6996
6997 bool lp_idmap_gid(gid_t *low, gid_t *high)
6998 {
6999         if (idmap_gid_low == 0 || idmap_gid_high == 0)
7000                 return False;
7001
7002         if (low)
7003                 *low = idmap_gid_low;
7004
7005         if (high)
7006                 *high = idmap_gid_high;
7007
7008         return True;
7009 }
7010
7011 /* Do some simple checks on "idmap [ug]id" parameter values */
7012
7013 static bool handle_idmap_uid(int snum, const char *pszParmValue, char **ptr)
7014 {
7015         uint32 low, high;
7016
7017         if (sscanf(pszParmValue, "%u - %u", &low, &high) != 2 || high < low)
7018                 return False;
7019
7020         /* Parse OK */
7021
7022         string_set(ptr, pszParmValue);
7023
7024         idmap_uid_low = low;
7025         idmap_uid_high = high;
7026
7027         return True;
7028 }
7029
7030 static bool handle_idmap_gid(int snum, const char *pszParmValue, char **ptr)
7031 {
7032         uint32 low, high;
7033
7034         if (sscanf(pszParmValue, "%u - %u", &low, &high) != 2 || high < low)
7035                 return False;
7036
7037         /* Parse OK */
7038
7039         string_set(ptr, pszParmValue);
7040
7041         idmap_gid_low = low;
7042         idmap_gid_high = high;
7043
7044         return True;
7045 }
7046
7047 /***************************************************************************
7048  Handle the DEBUG level list.
7049 ***************************************************************************/
7050
7051 static bool handle_debug_list( int snum, const char *pszParmValueIn, char **ptr )
7052 {
7053         string_set(ptr, pszParmValueIn);
7054         return debug_parse_levels(pszParmValueIn);
7055 }
7056
7057 /***************************************************************************
7058  Handle ldap suffixes - default to ldapsuffix if sub-suffixes are not defined.
7059 ***************************************************************************/
7060
7061 static const char *append_ldap_suffix( const char *str )
7062 {
7063         const char *suffix_string;
7064
7065
7066         suffix_string = talloc_asprintf(talloc_tos(), "%s,%s", str,
7067                                         Globals.szLdapSuffix );
7068         if ( !suffix_string ) {
7069                 DEBUG(0,("append_ldap_suffix: talloc_asprintf() failed!\n"));
7070                 return "";
7071         }
7072
7073         return suffix_string;
7074 }
7075
7076 const char *lp_ldap_machine_suffix(void)
7077 {
7078         if (Globals.szLdapMachineSuffix[0])
7079                 return append_ldap_suffix(Globals.szLdapMachineSuffix);
7080
7081         return lp_string(Globals.szLdapSuffix);
7082 }
7083
7084 const char *lp_ldap_user_suffix(void)
7085 {
7086         if (Globals.szLdapUserSuffix[0])
7087                 return append_ldap_suffix(Globals.szLdapUserSuffix);
7088
7089         return lp_string(Globals.szLdapSuffix);
7090 }
7091
7092 const char *lp_ldap_group_suffix(void)
7093 {
7094         if (Globals.szLdapGroupSuffix[0])
7095                 return append_ldap_suffix(Globals.szLdapGroupSuffix);
7096
7097         return lp_string(Globals.szLdapSuffix);
7098 }
7099
7100 const char *lp_ldap_idmap_suffix(void)
7101 {
7102         if (Globals.szLdapIdmapSuffix[0])
7103                 return append_ldap_suffix(Globals.szLdapIdmapSuffix);
7104
7105         return lp_string(Globals.szLdapSuffix);
7106 }
7107
7108 /****************************************************************************
7109  set the value for a P_ENUM
7110  ***************************************************************************/
7111
7112 static void lp_set_enum_parm( struct parm_struct *parm, const char *pszParmValue,
7113                               int *ptr )
7114 {
7115         int i;
7116
7117         for (i = 0; parm->enum_list[i].name; i++) {
7118                 if ( strequal(pszParmValue, parm->enum_list[i].name)) {
7119                         *ptr = parm->enum_list[i].value;
7120                         return;
7121                 }
7122         }
7123         DEBUG(0, ("WARNING: Ignoring invalid value '%s' for parameter '%s'\n",
7124                   pszParmValue, parm->label));
7125 }
7126
7127 /***************************************************************************
7128 ***************************************************************************/
7129
7130 static bool handle_printing(int snum, const char *pszParmValue, char **ptr)
7131 {
7132         static int parm_num = -1;
7133         struct service *s;
7134
7135         if ( parm_num == -1 )
7136                 parm_num = map_parameter( "printing" );
7137
7138         lp_set_enum_parm( &parm_table[parm_num], pszParmValue, (int*)ptr );
7139
7140         if ( snum < 0 )
7141                 s = &sDefault;
7142         else
7143                 s = ServicePtrs[snum];
7144
7145         init_printer_values( s );
7146
7147         return True;
7148 }
7149
7150
7151 /***************************************************************************
7152  Initialise a copymap.
7153 ***************************************************************************/
7154
7155 static void init_copymap(struct service *pservice)
7156 {
7157         int i;
7158         if (pservice->copymap) {
7159                 bitmap_free(pservice->copymap);
7160         }
7161         pservice->copymap = bitmap_allocate(NUMPARAMETERS);
7162         if (!pservice->copymap)
7163                 DEBUG(0,
7164                       ("Couldn't allocate copymap!! (size %d)\n",
7165                        (int)NUMPARAMETERS));
7166         else
7167                 for (i = 0; i < NUMPARAMETERS; i++)
7168                         bitmap_set(pservice->copymap, i);
7169 }
7170
7171 /***************************************************************************
7172  Return the local pointer to a parameter given a service struct and the
7173  pointer into the default structure.
7174 ***************************************************************************/
7175
7176 static void *lp_local_ptr(struct service *service, void *ptr)
7177 {
7178         return (void *)(((char *)service) + PTR_DIFF(ptr, &sDefault));
7179 }
7180
7181 /***************************************************************************
7182  Return the local pointer to a parameter given the service number and the 
7183  pointer into the default structure.
7184 ***************************************************************************/
7185
7186 void *lp_local_ptr_by_snum(int snum, void *ptr)
7187 {
7188         return lp_local_ptr(ServicePtrs[snum], ptr);
7189 }
7190
7191 /***************************************************************************
7192  Process a parameter for a particular service number. If snum < 0
7193  then assume we are in the globals.
7194 ***************************************************************************/
7195
7196 bool lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue)
7197 {
7198         int parmnum, i;
7199         void *parm_ptr = NULL;  /* where we are going to store the result */
7200         void *def_ptr = NULL;
7201         struct param_opt_struct **opt_list;
7202
7203         parmnum = map_parameter(pszParmName);
7204
7205         if (parmnum < 0) {
7206                 if (strchr(pszParmName, ':') == NULL) {
7207                         DEBUG(0, ("Ignoring unknown parameter \"%s\"\n",
7208                                   pszParmName));
7209                         return (True);
7210                 }
7211
7212                 /*
7213                  * We've got a parametric option
7214                  */
7215
7216                 opt_list = (snum < 0)
7217                         ? &Globals.param_opt : &ServicePtrs[snum]->param_opt;
7218                 set_param_opt(opt_list, pszParmName, pszParmValue);
7219
7220                 return (True);
7221         }
7222
7223         if (parm_table[parmnum].flags & FLAG_DEPRECATED) {
7224                 DEBUG(1, ("WARNING: The \"%s\" option is deprecated\n",
7225                           pszParmName));
7226         }
7227
7228         def_ptr = parm_table[parmnum].ptr;
7229
7230         /* we might point at a service, the default service or a global */
7231         if (snum < 0) {
7232                 parm_ptr = def_ptr;
7233         } else {
7234                 if (parm_table[parmnum].p_class == P_GLOBAL) {
7235                         DEBUG(0,
7236                               ("Global parameter %s found in service section!\n",
7237                                pszParmName));
7238                         return (True);
7239                 }
7240                 parm_ptr = lp_local_ptr_by_snum(snum, def_ptr);
7241         }
7242
7243         if (snum >= 0) {
7244                 if (!ServicePtrs[snum]->copymap)
7245                         init_copymap(ServicePtrs[snum]);
7246
7247                 /* this handles the aliases - set the copymap for other entries with
7248                    the same data pointer */
7249                 for (i = 0; parm_table[i].label; i++)
7250                         if (parm_table[i].ptr == parm_table[parmnum].ptr)
7251                                 bitmap_clear(ServicePtrs[snum]->copymap, i);
7252         }
7253
7254         /* if it is a special case then go ahead */
7255         if (parm_table[parmnum].special) {
7256                 return parm_table[parmnum].special(snum, pszParmValue,
7257                                                    (char **)parm_ptr);
7258         }
7259
7260         /* now switch on the type of variable it is */
7261         switch (parm_table[parmnum].type)
7262         {
7263                 case P_BOOL:
7264                         *(bool *)parm_ptr = lp_bool(pszParmValue);
7265                         break;
7266
7267                 case P_BOOLREV:
7268                         *(bool *)parm_ptr = !lp_bool(pszParmValue);
7269                         break;
7270
7271                 case P_INTEGER:
7272                         *(int *)parm_ptr = lp_int(pszParmValue);
7273                         break;
7274
7275                 case P_CHAR:
7276                         *(char *)parm_ptr = *pszParmValue;
7277                         break;
7278
7279                 case P_OCTAL:
7280                         i = sscanf(pszParmValue, "%o", (int *)parm_ptr);
7281                         if ( i != 1 ) {
7282                             DEBUG ( 0, ("Invalid octal number %s\n", pszParmName ));
7283                         }
7284                         break;
7285
7286                 case P_LIST:
7287                         TALLOC_FREE(*((char ***)parm_ptr));
7288                         *(char ***)parm_ptr = str_list_make_v3(
7289                                 talloc_autofree_context(), pszParmValue, NULL);
7290                         break;
7291
7292                 case P_STRING:
7293                         string_set((char **)parm_ptr, pszParmValue);
7294                         break;
7295
7296                 case P_USTRING:
7297                         string_set((char **)parm_ptr, pszParmValue);
7298                         strupper_m(*(char **)parm_ptr);
7299                         break;
7300
7301                 case P_ENUM:
7302                         lp_set_enum_parm( &parm_table[parmnum], pszParmValue, (int*)parm_ptr );
7303                         break;
7304                 case P_SEP:
7305                         break;
7306         }
7307
7308         return (True);
7309 }
7310
7311 /***************************************************************************
7312  Process a parameter.
7313 ***************************************************************************/
7314
7315 static bool do_parameter(const char *pszParmName, const char *pszParmValue,
7316                          void *userdata)
7317 {
7318         if (!bInGlobalSection && bGlobalOnly)
7319                 return (True);
7320
7321         DEBUGADD(4, ("doing parameter %s = %s\n", pszParmName, pszParmValue));
7322
7323         return (lp_do_parameter(bInGlobalSection ? -2 : iServiceIndex,
7324                                 pszParmName, pszParmValue));
7325 }
7326
7327 /***************************************************************************
7328  Print a parameter of the specified type.
7329 ***************************************************************************/
7330
7331 static void print_parameter(struct parm_struct *p, void *ptr, FILE * f)
7332 {
7333         int i;
7334         switch (p->type)
7335         {
7336                 case P_ENUM:
7337                         for (i = 0; p->enum_list[i].name; i++) {
7338                                 if (*(int *)ptr == p->enum_list[i].value) {
7339                                         fprintf(f, "%s",
7340                                                 p->enum_list[i].name);
7341                                         break;
7342                                 }
7343                         }
7344                         break;
7345
7346                 case P_BOOL:
7347                         fprintf(f, "%s", BOOLSTR(*(bool *)ptr));
7348                         break;
7349
7350                 case P_BOOLREV:
7351                         fprintf(f, "%s", BOOLSTR(!*(bool *)ptr));
7352                         break;
7353
7354                 case P_INTEGER:
7355                         fprintf(f, "%d", *(int *)ptr);
7356                         break;
7357
7358                 case P_CHAR:
7359                         fprintf(f, "%c", *(char *)ptr);
7360                         break;
7361
7362                 case P_OCTAL: {
7363                         char *o = octal_string(*(int *)ptr);
7364                         fprintf(f, "%s", o);
7365                         TALLOC_FREE(o);
7366                         break;
7367                 }
7368
7369                 case P_LIST:
7370                         if ((char ***)ptr && *(char ***)ptr) {
7371                                 char **list = *(char ***)ptr;
7372                                 for (; *list; list++) {
7373                                         /* surround strings with whitespace in double quotes */
7374                                         if ( strchr_m( *list, ' ' ) )
7375                                                 fprintf(f, "\"%s\"%s", *list, ((*(list+1))?", ":""));
7376                                         else
7377                                                 fprintf(f, "%s%s", *list, ((*(list+1))?", ":""));
7378                                 }
7379                         }
7380                         break;
7381
7382                 case P_STRING:
7383                 case P_USTRING:
7384                         if (*(char **)ptr) {
7385                                 fprintf(f, "%s", *(char **)ptr);
7386                         }
7387                         break;
7388                 case P_SEP:
7389                         break;
7390         }
7391 }
7392
7393 /***************************************************************************
7394  Check if two parameters are equal.
7395 ***************************************************************************/
7396
7397 static bool equal_parameter(parm_type type, void *ptr1, void *ptr2)
7398 {
7399         switch (type) {
7400                 case P_BOOL:
7401                 case P_BOOLREV:
7402                         return (*((bool *)ptr1) == *((bool *)ptr2));
7403
7404                 case P_INTEGER:
7405                 case P_ENUM:
7406                 case P_OCTAL:
7407                         return (*((int *)ptr1) == *((int *)ptr2));
7408
7409                 case P_CHAR:
7410                         return (*((char *)ptr1) == *((char *)ptr2));
7411
7412                 case P_LIST:
7413                         return str_list_equal(*(const char ***)ptr1, *(const char ***)ptr2);
7414
7415                 case P_STRING:
7416                 case P_USTRING:
7417                 {
7418                         char *p1 = *(char **)ptr1, *p2 = *(char **)ptr2;
7419                         if (p1 && !*p1)
7420                                 p1 = NULL;
7421                         if (p2 && !*p2)
7422                                 p2 = NULL;
7423                         return (p1 == p2 || strequal(p1, p2));
7424                 }
7425                 case P_SEP:
7426                         break;
7427         }
7428         return (False);
7429 }
7430
7431 /***************************************************************************
7432  Initialize any local varients in the sDefault table.
7433 ***************************************************************************/
7434
7435 void init_locals(void)
7436 {
7437         /* None as yet. */
7438 }
7439
7440 /***************************************************************************
7441  Process a new section (service). At this stage all sections are services.
7442  Later we'll have special sections that permit server parameters to be set.
7443  Returns True on success, False on failure. 
7444 ***************************************************************************/
7445
7446 static bool do_section(const char *pszSectionName, void *userdata)
7447 {
7448         bool bRetval;
7449         bool isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
7450                          (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
7451         bRetval = False;
7452
7453         /* if we were in a global section then do the local inits */
7454         if (bInGlobalSection && !isglobal)
7455                 init_locals();
7456
7457         /* if we've just struck a global section, note the fact. */
7458         bInGlobalSection = isglobal;
7459
7460         /* check for multiple global sections */
7461         if (bInGlobalSection) {
7462                 DEBUG(3, ("Processing section \"[%s]\"\n", pszSectionName));
7463                 return (True);
7464         }
7465
7466         if (!bInGlobalSection && bGlobalOnly)
7467                 return (True);
7468
7469         /* if we have a current service, tidy it up before moving on */
7470         bRetval = True;
7471
7472         if (iServiceIndex >= 0)
7473                 bRetval = service_ok(iServiceIndex);
7474
7475         /* if all is still well, move to the next record in the services array */
7476         if (bRetval) {
7477                 /* We put this here to avoid an odd message order if messages are */
7478                 /* issued by the post-processing of a previous section. */
7479                 DEBUG(2, ("Processing section \"[%s]\"\n", pszSectionName));
7480
7481                 if ((iServiceIndex = add_a_service(&sDefault, pszSectionName))
7482                     < 0) {
7483                         DEBUG(0, ("Failed to add a new service\n"));
7484                         return (False);
7485                 }
7486         }
7487
7488         return (bRetval);
7489 }
7490
7491
7492 /***************************************************************************
7493  Determine if a partcular base parameter is currentl set to the default value.
7494 ***************************************************************************/
7495
7496 static bool is_default(int i)
7497 {
7498         if (!defaults_saved)
7499                 return False;
7500         switch (parm_table[i].type) {
7501                 case P_LIST:
7502                         return str_list_equal((const char **)parm_table[i].def.lvalue, 
7503                                                 *(const char ***)parm_table[i].ptr);
7504                 case P_STRING:
7505                 case P_USTRING:
7506                         return strequal(parm_table[i].def.svalue,
7507                                         *(char **)parm_table[i].ptr);
7508                 case P_BOOL:
7509                 case P_BOOLREV:
7510                         return parm_table[i].def.bvalue ==
7511                                 *(bool *)parm_table[i].ptr;
7512                 case P_CHAR:
7513                         return parm_table[i].def.cvalue ==
7514                                 *(char *)parm_table[i].ptr;
7515                 case P_INTEGER:
7516                 case P_OCTAL:
7517                 case P_ENUM:
7518                         return parm_table[i].def.ivalue ==
7519                                 *(int *)parm_table[i].ptr;
7520                 case P_SEP:
7521                         break;
7522         }
7523         return False;
7524 }
7525
7526 /***************************************************************************
7527 Display the contents of the global structure.
7528 ***************************************************************************/
7529
7530 static void dump_globals(FILE *f)
7531 {
7532         int i;
7533         struct param_opt_struct *data;
7534         
7535         fprintf(f, "[global]\n");
7536
7537         for (i = 0; parm_table[i].label; i++)
7538                 if (parm_table[i].p_class == P_GLOBAL &&
7539                     parm_table[i].ptr &&
7540                     (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) {
7541                         if (defaults_saved && is_default(i))
7542                                 continue;
7543                         fprintf(f, "\t%s = ", parm_table[i].label);
7544                         print_parameter(&parm_table[i], parm_table[i].ptr, f);
7545                         fprintf(f, "\n");
7546         }
7547         if (Globals.param_opt != NULL) {
7548                 data = Globals.param_opt;
7549                 while(data) {
7550                         fprintf(f, "\t%s = %s\n", data->key, data->value);
7551                         data = data->next;
7552                 }
7553         }
7554
7555 }
7556
7557 /***************************************************************************
7558  Return True if a local parameter is currently set to the global default.
7559 ***************************************************************************/
7560
7561 bool lp_is_default(int snum, struct parm_struct *parm)
7562 {
7563         int pdiff = PTR_DIFF(parm->ptr, &sDefault);
7564
7565         return equal_parameter(parm->type,
7566                                ((char *)ServicePtrs[snum]) + pdiff,
7567                                ((char *)&sDefault) + pdiff);
7568 }
7569
7570 /***************************************************************************
7571  Display the contents of a single services record.
7572 ***************************************************************************/
7573
7574 static void dump_a_service(struct service *pService, FILE * f)
7575 {
7576         int i;
7577         struct param_opt_struct *data;
7578         
7579         if (pService != &sDefault)
7580                 fprintf(f, "[%s]\n", pService->szService);
7581
7582         for (i = 0; parm_table[i].label; i++) {
7583
7584                 if (parm_table[i].p_class == P_LOCAL &&
7585                     parm_table[i].ptr &&
7586                     (*parm_table[i].label != '-') &&
7587                     (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) 
7588                 {
7589                 
7590                         int pdiff = PTR_DIFF(parm_table[i].ptr, &sDefault);
7591
7592                         if (pService == &sDefault) {
7593                                 if (defaults_saved && is_default(i))
7594                                         continue;
7595                         } else {
7596                                 if (equal_parameter(parm_table[i].type,
7597                                                     ((char *)pService) +
7598                                                     pdiff,
7599                                                     ((char *)&sDefault) +
7600                                                     pdiff))
7601                                         continue;
7602                         }
7603
7604                         fprintf(f, "\t%s = ", parm_table[i].label);
7605                         print_parameter(&parm_table[i],
7606                                         ((char *)pService) + pdiff, f);
7607                         fprintf(f, "\n");
7608                 }
7609         }
7610
7611                 if (pService->param_opt != NULL) {
7612                         data = pService->param_opt;
7613                         while(data) {
7614                                 fprintf(f, "\t%s = %s\n", data->key, data->value);
7615                                 data = data->next;
7616                         }
7617                 }
7618 }
7619
7620 /***************************************************************************
7621  Display the contents of a parameter of a single services record.
7622 ***************************************************************************/
7623
7624 bool dump_a_parameter(int snum, char *parm_name, FILE * f, bool isGlobal)
7625 {
7626         int i;
7627         bool result = False;
7628         parm_class p_class;
7629         unsigned flag = 0;
7630         fstring local_parm_name;
7631         char *parm_opt;
7632         const char *parm_opt_value;
7633
7634         /* check for parametrical option */
7635         fstrcpy( local_parm_name, parm_name);
7636         parm_opt = strchr( local_parm_name, ':');
7637
7638         if (parm_opt) {
7639                 *parm_opt = '\0';
7640                 parm_opt++;
7641                 if (strlen(parm_opt)) {
7642                         parm_opt_value = lp_parm_const_string( snum,
7643                                 local_parm_name, parm_opt, NULL);
7644                         if (parm_opt_value) {
7645                                 printf( "%s\n", parm_opt_value);
7646                                 result = True;
7647                         }
7648                 }
7649                 return result;
7650         }
7651
7652         /* check for a key and print the value */
7653         if (isGlobal) {
7654                 p_class = P_GLOBAL;
7655                 flag = FLAG_GLOBAL;
7656         } else
7657                 p_class = P_LOCAL;
7658
7659         for (i = 0; parm_table[i].label; i++) {
7660                 if (strwicmp(parm_table[i].label, parm_name) == 0 &&
7661                     (parm_table[i].p_class == p_class || parm_table[i].flags & flag) &&
7662                     parm_table[i].ptr &&
7663                     (*parm_table[i].label != '-') &&
7664                     (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) 
7665                 {
7666                         void *ptr;
7667
7668                         if (isGlobal) {
7669                                 ptr = parm_table[i].ptr;
7670                         } else {
7671                                 struct service *pService = ServicePtrs[snum];
7672                                 ptr = ((char *)pService) +
7673                                         PTR_DIFF(parm_table[i].ptr, &sDefault);
7674                         }
7675
7676                         print_parameter(&parm_table[i],
7677                                         ptr, f);
7678                         fprintf(f, "\n");
7679                         result = True;
7680                         break;
7681                 }
7682         }
7683
7684         return result;
7685 }
7686
7687 /***************************************************************************
7688  Return info about the requested parameter (given as a string).
7689  Return NULL when the string is not a valid parameter name.
7690 ***************************************************************************/
7691
7692 struct parm_struct *lp_get_parameter(const char *param_name)
7693 {
7694         int num = map_parameter(param_name);
7695
7696         if (num < 0) {
7697                 return NULL;
7698         }
7699
7700         return &parm_table[num];
7701 }
7702
7703 /***************************************************************************
7704  Return info about the next parameter in a service.
7705  snum==GLOBAL_SECTION_SNUM gives the globals.
7706  Return NULL when out of parameters.
7707 ***************************************************************************/
7708
7709 struct parm_struct *lp_next_parameter(int snum, int *i, int allparameters)
7710 {
7711         if (snum < 0) {
7712                 /* do the globals */
7713                 for (; parm_table[*i].label; (*i)++) {
7714                         if (parm_table[*i].p_class == P_SEPARATOR)
7715                                 return &parm_table[(*i)++];
7716
7717                         if (!parm_table[*i].ptr
7718                             || (*parm_table[*i].label == '-'))
7719                                 continue;
7720
7721                         if ((*i) > 0
7722                             && (parm_table[*i].ptr ==
7723                                 parm_table[(*i) - 1].ptr))
7724                                 continue;
7725                         
7726                         if (is_default(*i) && !allparameters)
7727                                 continue;
7728
7729                         return &parm_table[(*i)++];
7730                 }
7731         } else {
7732                 struct service *pService = ServicePtrs[snum];
7733
7734                 for (; parm_table[*i].label; (*i)++) {
7735                         if (parm_table[*i].p_class == P_SEPARATOR)
7736                                 return &parm_table[(*i)++];
7737
7738                         if (parm_table[*i].p_class == P_LOCAL &&
7739                             parm_table[*i].ptr &&
7740                             (*parm_table[*i].label != '-') &&
7741                             ((*i) == 0 ||
7742                              (parm_table[*i].ptr !=
7743                               parm_table[(*i) - 1].ptr)))
7744                         {
7745                                 int pdiff =
7746                                         PTR_DIFF(parm_table[*i].ptr,
7747                                                  &sDefault);
7748
7749                                 if (allparameters ||
7750                                     !equal_parameter(parm_table[*i].type,
7751                                                      ((char *)pService) +
7752                                                      pdiff,
7753                                                      ((char *)&sDefault) +
7754                                                      pdiff))
7755                                 {
7756                                         return &parm_table[(*i)++];
7757                                 }
7758                         }
7759                 }
7760         }
7761
7762         return NULL;
7763 }
7764
7765
7766 #if 0
7767 /***************************************************************************
7768  Display the contents of a single copy structure.
7769 ***************************************************************************/
7770 static void dump_copy_map(bool *pcopymap)
7771 {
7772         int i;
7773         if (!pcopymap)
7774                 return;
7775
7776         printf("\n\tNon-Copied parameters:\n");
7777
7778         for (i = 0; parm_table[i].label; i++)
7779                 if (parm_table[i].p_class == P_LOCAL &&
7780                     parm_table[i].ptr && !pcopymap[i] &&
7781                     (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr)))
7782                 {
7783                         printf("\t\t%s\n", parm_table[i].label);
7784                 }
7785 }
7786 #endif
7787
7788 /***************************************************************************
7789  Return TRUE if the passed service number is within range.
7790 ***************************************************************************/
7791
7792 bool lp_snum_ok(int iService)
7793 {
7794         return (LP_SNUM_OK(iService) && ServicePtrs[iService]->bAvailable);
7795 }
7796
7797 /***************************************************************************
7798  Auto-load some home services.
7799 ***************************************************************************/
7800
7801 static void lp_add_auto_services(char *str)
7802 {
7803         char *s;
7804         char *p;
7805         int homes;
7806         char *saveptr;
7807
7808         if (!str)
7809                 return;
7810
7811         s = SMB_STRDUP(str);
7812         if (!s)
7813                 return;
7814
7815         homes = lp_servicenumber(HOMES_NAME);
7816
7817         for (p = strtok_r(s, LIST_SEP, &saveptr); p;
7818              p = strtok_r(NULL, LIST_SEP, &saveptr)) {
7819                 char *home;
7820
7821                 if (lp_servicenumber(p) >= 0)
7822                         continue;
7823
7824                 home = get_user_home_dir(talloc_tos(), p);
7825
7826                 if (home && homes >= 0)
7827                         lp_add_home(p, homes, p, home);
7828
7829                 TALLOC_FREE(home);
7830         }
7831         SAFE_FREE(s);
7832 }
7833
7834 /***************************************************************************
7835  Auto-load one printer.
7836 ***************************************************************************/
7837
7838 void lp_add_one_printer(const char *name, const char *comment, void *pdata)
7839 {
7840         int printers = lp_servicenumber(PRINTERS_NAME);
7841         int i;
7842
7843         if (lp_servicenumber(name) < 0) {
7844                 lp_add_printer(name, printers);
7845                 if ((i = lp_servicenumber(name)) >= 0) {
7846                         string_set(&ServicePtrs[i]->comment, comment);
7847                         ServicePtrs[i]->autoloaded = True;
7848                 }
7849         }
7850 }
7851
7852 /***************************************************************************
7853  Have we loaded a services file yet?
7854 ***************************************************************************/
7855
7856 bool lp_loaded(void)
7857 {
7858         return (bLoaded);
7859 }
7860
7861 /***************************************************************************
7862  Unload unused services.
7863 ***************************************************************************/
7864
7865 void lp_killunused(bool (*snumused) (int))
7866 {
7867         int i;
7868         for (i = 0; i < iNumServices; i++) {
7869                 if (!VALID(i))
7870                         continue;
7871
7872                 /* don't kill autoloaded or usershare services */
7873                 if ( ServicePtrs[i]->autoloaded ||
7874                                 ServicePtrs[i]->usershare == USERSHARE_VALID) {
7875                         continue;
7876                 }
7877
7878                 if (!snumused || !snumused(i)) {
7879                         free_service_byindex(i);
7880                 }
7881         }
7882 }
7883
7884 /**
7885  * Kill all except autoloaded and usershare services - convenience wrapper
7886  */
7887 void lp_kill_all_services(void)
7888 {
7889         lp_killunused(NULL);
7890 }
7891
7892 /***************************************************************************
7893  Unload a service.
7894 ***************************************************************************/
7895
7896 void lp_killservice(int iServiceIn)
7897 {
7898         if (VALID(iServiceIn)) {
7899                 free_service_byindex(iServiceIn);
7900         }
7901 }
7902
7903 /***************************************************************************
7904  Save the curent values of all global and sDefault parameters into the 
7905  defaults union. This allows swat and testparm to show only the
7906  changed (ie. non-default) parameters.
7907 ***************************************************************************/
7908
7909 static void lp_save_defaults(void)
7910 {
7911         int i;
7912         for (i = 0; parm_table[i].label; i++) {
7913                 if (i > 0 && parm_table[i].ptr == parm_table[i - 1].ptr)
7914                         continue;
7915                 switch (parm_table[i].type) {
7916                         case P_LIST:
7917                                 parm_table[i].def.lvalue = str_list_copy(
7918                                         NULL, *(const char ***)parm_table[i].ptr);
7919                                 break;
7920                         case P_STRING:
7921                         case P_USTRING:
7922                                 if (parm_table[i].ptr) {
7923                                         parm_table[i].def.svalue = SMB_STRDUP(*(char **)parm_table[i].ptr);
7924                                 } else {
7925                                         parm_table[i].def.svalue = NULL;
7926                                 }
7927                                 break;
7928                         case P_BOOL:
7929                         case P_BOOLREV:
7930                                 parm_table[i].def.bvalue =
7931                                         *(bool *)parm_table[i].ptr;
7932                                 break;
7933                         case P_CHAR:
7934                                 parm_table[i].def.cvalue =
7935                                         *(char *)parm_table[i].ptr;
7936                                 break;
7937                         case P_INTEGER:
7938                         case P_OCTAL:
7939                         case P_ENUM:
7940                                 parm_table[i].def.ivalue =
7941                                         *(int *)parm_table[i].ptr;
7942                                 break;
7943                         case P_SEP:
7944                                 break;
7945                 }
7946         }
7947         defaults_saved = True;
7948 }
7949
7950 /*******************************************************************
7951  Set the server type we will announce as via nmbd.
7952 ********************************************************************/
7953
7954 static const struct srv_role_tab {
7955         uint32 role;
7956         const char *role_str;
7957 } srv_role_tab [] = {
7958         { ROLE_STANDALONE, "ROLE_STANDALONE" },
7959         { ROLE_DOMAIN_MEMBER, "ROLE_DOMAIN_MEMBER" },
7960         { ROLE_DOMAIN_BDC, "ROLE_DOMAIN_BDC" },
7961         { ROLE_DOMAIN_PDC, "ROLE_DOMAIN_PDC" },
7962         { 0, NULL }
7963 };
7964
7965 const char* server_role_str(uint32 role)
7966 {
7967         int i = 0;
7968         for (i=0; srv_role_tab[i].role_str; i++) {
7969                 if (role == srv_role_tab[i].role) {
7970                         return srv_role_tab[i].role_str;
7971                 }
7972         }
7973         return NULL;
7974 }
7975
7976 static void set_server_role(void)
7977 {
7978         server_role = ROLE_STANDALONE;
7979
7980         switch (lp_security()) {
7981                 case SEC_SHARE:
7982                         if (lp_domain_logons())
7983                                 DEBUG(0, ("Server's Role (logon server) conflicts with share-level security\n"));
7984                         break;
7985                 case SEC_SERVER:
7986                         if (lp_domain_logons())
7987                                 DEBUG(0, ("Server's Role (logon server) conflicts with server-level security\n"));
7988                         /* this used to be considered ROLE_DOMAIN_MEMBER but that's just wrong */
7989                         server_role = ROLE_STANDALONE;
7990                         break;
7991                 case SEC_DOMAIN:
7992                         if (lp_domain_logons()) {
7993                                 DEBUG(1, ("Server's Role (logon server) NOT ADVISED with domain-level security\n"));
7994                                 server_role = ROLE_DOMAIN_BDC;
7995                                 break;
7996                         }
7997                         server_role = ROLE_DOMAIN_MEMBER;
7998                         break;
7999                 case SEC_ADS:
8000                         if (lp_domain_logons()) {
8001                                 server_role = ROLE_DOMAIN_PDC;
8002                                 break;
8003                         }
8004                         server_role = ROLE_DOMAIN_MEMBER;
8005                         break;
8006                 case SEC_USER:
8007                         if (lp_domain_logons()) {
8008
8009                                 if (Globals.iDomainMaster) /* auto or yes */ 
8010                                         server_role = ROLE_DOMAIN_PDC;
8011                                 else
8012                                         server_role = ROLE_DOMAIN_BDC;
8013                         }
8014                         break;
8015                 default:
8016                         DEBUG(0, ("Server's Role undefined due to unknown security mode\n"));
8017                         break;
8018         }
8019
8020         DEBUG(10, ("set_server_role: role = %s\n", server_role_str(server_role)));
8021 }
8022
8023 /***********************************************************
8024  If we should send plaintext/LANMAN passwords in the clinet
8025 ************************************************************/
8026
8027 static void set_allowed_client_auth(void)
8028 {
8029         if (Globals.bClientNTLMv2Auth) {
8030                 Globals.bClientLanManAuth = False;
8031         }
8032         if (!Globals.bClientLanManAuth) {
8033                 Globals.bClientPlaintextAuth = False;
8034         }
8035 }
8036
8037 /***************************************************************************
8038  JRA.
8039  The following code allows smbd to read a user defined share file.
8040  Yes, this is my intent. Yes, I'm comfortable with that...
8041
8042  THE FOLLOWING IS SECURITY CRITICAL CODE.
8043
8044  It washes your clothes, it cleans your house, it guards you while you sleep...
8045  Do not f%^k with it....
8046 ***************************************************************************/
8047
8048 #define MAX_USERSHARE_FILE_SIZE (10*1024)
8049
8050 /***************************************************************************
8051  Check allowed stat state of a usershare file.
8052  Ensure we print out who is dicking with us so the admin can
8053  get their sorry ass fired.
8054 ***************************************************************************/
8055
8056 static bool check_usershare_stat(const char *fname, SMB_STRUCT_STAT *psbuf)
8057 {
8058         if (!S_ISREG(psbuf->st_mode)) {
8059                 DEBUG(0,("check_usershare_stat: file %s owned by uid %u is "
8060                         "not a regular file\n",
8061                         fname, (unsigned int)psbuf->st_uid ));
8062                 return False;
8063         }
8064
8065         /* Ensure this doesn't have the other write bit set. */
8066         if (psbuf->st_mode & S_IWOTH) {
8067                 DEBUG(0,("check_usershare_stat: file %s owned by uid %u allows "
8068                         "public write. Refusing to allow as a usershare file.\n",
8069                         fname, (unsigned int)psbuf->st_uid ));
8070                 return False;
8071         }
8072
8073         /* Should be 10k or less. */
8074         if (psbuf->st_size > MAX_USERSHARE_FILE_SIZE) {
8075                 DEBUG(0,("check_usershare_stat: file %s owned by uid %u is "
8076                         "too large (%u) to be a user share file.\n",
8077                         fname, (unsigned int)psbuf->st_uid,
8078                         (unsigned int)psbuf->st_size ));
8079                 return False;
8080         }
8081
8082         return True;
8083 }
8084
8085 /***************************************************************************
8086  Parse the contents of a usershare file.
8087 ***************************************************************************/
8088
8089 enum usershare_err parse_usershare_file(TALLOC_CTX *ctx,
8090                         SMB_STRUCT_STAT *psbuf,
8091                         const char *servicename,
8092                         int snum,
8093                         char **lines,
8094                         int numlines,
8095                         char **pp_sharepath,
8096                         char **pp_comment,
8097                         SEC_DESC **ppsd,
8098                         bool *pallow_guest)
8099 {
8100         const char **prefixallowlist = lp_usershare_prefix_allow_list();
8101         const char **prefixdenylist = lp_usershare_prefix_deny_list();
8102         int us_vers;
8103         SMB_STRUCT_DIR *dp;
8104         SMB_STRUCT_STAT sbuf;
8105         char *sharepath = NULL;
8106         char *comment = NULL;
8107
8108         *pp_sharepath = NULL;
8109         *pp_comment = NULL;
8110
8111         *pallow_guest = False;
8112
8113         if (numlines < 4) {
8114                 return USERSHARE_MALFORMED_FILE;
8115         }
8116
8117         if (strcmp(lines[0], "#VERSION 1") == 0) {
8118                 us_vers = 1;
8119         } else if (strcmp(lines[0], "#VERSION 2") == 0) {
8120                 us_vers = 2;
8121                 if (numlines < 5) {
8122                         return USERSHARE_MALFORMED_FILE;
8123                 }
8124         } else {
8125                 return USERSHARE_BAD_VERSION;
8126         }
8127
8128         if (strncmp(lines[1], "path=", 5) != 0) {
8129                 return USERSHARE_MALFORMED_PATH;
8130         }
8131
8132         sharepath = talloc_strdup(ctx, &lines[1][5]);
8133         if (!sharepath) {
8134                 return USERSHARE_POSIX_ERR;
8135         }
8136         trim_string(sharepath, " ", " ");
8137
8138         if (strncmp(lines[2], "comment=", 8) != 0) {
8139                 return USERSHARE_MALFORMED_COMMENT_DEF;
8140         }
8141
8142         comment = talloc_strdup(ctx, &lines[2][8]);
8143         if (!comment) {
8144                 return USERSHARE_POSIX_ERR;
8145         }
8146         trim_string(comment, " ", " ");
8147         trim_char(comment, '"', '"');
8148
8149         if (strncmp(lines[3], "usershare_acl=", 14) != 0) {
8150                 return USERSHARE_MALFORMED_ACL_DEF;
8151         }
8152
8153         if (!parse_usershare_acl(ctx, &lines[3][14], ppsd)) {
8154                 return USERSHARE_ACL_ERR;
8155         }
8156
8157         if (us_vers == 2) {
8158                 if (strncmp(lines[4], "guest_ok=", 9) != 0) {
8159                         return USERSHARE_MALFORMED_ACL_DEF;
8160                 }
8161                 if (lines[4][9] == 'y') {
8162                         *pallow_guest = True;
8163                 }
8164         }
8165
8166         if (snum != -1 && (strcmp(sharepath, ServicePtrs[snum]->szPath) == 0)) {
8167                 /* Path didn't change, no checks needed. */
8168                 *pp_sharepath = sharepath;
8169                 *pp_comment = comment;
8170                 return USERSHARE_OK;
8171         }
8172
8173         /* The path *must* be absolute. */
8174         if (sharepath[0] != '/') {
8175                 DEBUG(2,("parse_usershare_file: share %s: path %s is not an absolute path.\n",
8176                         servicename, sharepath));
8177                 return USERSHARE_PATH_NOT_ABSOLUTE;
8178         }
8179
8180         /* If there is a usershare prefix deny list ensure one of these paths
8181            doesn't match the start of the user given path. */
8182         if (prefixdenylist) {
8183                 int i;
8184                 for ( i=0; prefixdenylist[i]; i++ ) {
8185                         DEBUG(10,("parse_usershare_file: share %s : checking prefixdenylist[%d]='%s' against %s\n",
8186                                 servicename, i, prefixdenylist[i], sharepath ));
8187                         if (memcmp( sharepath, prefixdenylist[i], strlen(prefixdenylist[i])) == 0) {
8188                                 DEBUG(2,("parse_usershare_file: share %s path %s starts with one of the "
8189                                         "usershare prefix deny list entries.\n",
8190                                         servicename, sharepath));
8191                                 return USERSHARE_PATH_IS_DENIED;
8192                         }
8193                 }
8194         }
8195
8196         /* If there is a usershare prefix allow list ensure one of these paths
8197            does match the start of the user given path. */
8198
8199         if (prefixallowlist) {
8200                 int i;
8201                 for ( i=0; prefixallowlist[i]; i++ ) {
8202                         DEBUG(10,("parse_usershare_file: share %s checking prefixallowlist[%d]='%s' against %s\n",
8203                                 servicename, i, prefixallowlist[i], sharepath ));
8204                         if (memcmp( sharepath, prefixallowlist[i], strlen(prefixallowlist[i])) == 0) {
8205                                 break;
8206                         }
8207                 }
8208                 if (prefixallowlist[i] == NULL) {
8209                         DEBUG(2,("parse_usershare_file: share %s path %s doesn't start with one of the "
8210                                 "usershare prefix allow list entries.\n",
8211                                 servicename, sharepath));
8212                         return USERSHARE_PATH_NOT_ALLOWED;
8213                 }
8214         }
8215
8216         /* Ensure this is pointing to a directory. */
8217         dp = sys_opendir(sharepath);
8218
8219         if (!dp) {
8220                 DEBUG(2,("parse_usershare_file: share %s path %s is not a directory.\n",
8221                         servicename, sharepath));
8222                 return USERSHARE_PATH_NOT_DIRECTORY;
8223         }
8224
8225         /* Ensure the owner of the usershare file has permission to share
8226            this directory. */
8227
8228         if (sys_stat(sharepath, &sbuf) == -1) {
8229                 DEBUG(2,("parse_usershare_file: share %s : stat failed on path %s. %s\n",
8230                         servicename, sharepath, strerror(errno) ));
8231                 sys_closedir(dp);
8232                 return USERSHARE_POSIX_ERR;
8233         }
8234
8235         sys_closedir(dp);
8236
8237         if (!S_ISDIR(sbuf.st_mode)) {
8238                 DEBUG(2,("parse_usershare_file: share %s path %s is not a directory.\n",
8239                         servicename, sharepath ));
8240                 return USERSHARE_PATH_NOT_DIRECTORY;
8241         }
8242
8243         /* Check if sharing is restricted to owner-only. */
8244         /* psbuf is the stat of the usershare definition file,
8245            sbuf is the stat of the target directory to be shared. */
8246
8247         if (lp_usershare_owner_only()) {
8248                 /* root can share anything. */
8249                 if ((psbuf->st_uid != 0) && (sbuf.st_uid != psbuf->st_uid)) {
8250                         return USERSHARE_PATH_NOT_ALLOWED;
8251                 }
8252         }
8253
8254         *pp_sharepath = sharepath;
8255         *pp_comment = comment;
8256         return USERSHARE_OK;
8257 }
8258
8259 /***************************************************************************
8260  Deal with a usershare file.
8261  Returns:
8262         >= 0 - snum
8263         -1 - Bad name, invalid contents.
8264            - service name already existed and not a usershare, problem
8265             with permissions to share directory etc.
8266 ***************************************************************************/
8267
8268 static int process_usershare_file(const char *dir_name, const char *file_name, int snum_template)
8269 {
8270         SMB_STRUCT_STAT sbuf;
8271         SMB_STRUCT_STAT lsbuf;
8272         char *fname = NULL;
8273         char *sharepath = NULL;
8274         char *comment = NULL;
8275         fstring service_name;
8276         char **lines = NULL;
8277         int numlines = 0;
8278         int fd = -1;
8279         int iService = -1;
8280         TALLOC_CTX *ctx = NULL;
8281         SEC_DESC *psd = NULL;
8282         bool guest_ok = False;
8283
8284         /* Ensure share name doesn't contain invalid characters. */
8285         if (!validate_net_name(file_name, INVALID_SHARENAME_CHARS, strlen(file_name))) {
8286                 DEBUG(0,("process_usershare_file: share name %s contains "
8287                         "invalid characters (any of %s)\n",
8288                         file_name, INVALID_SHARENAME_CHARS ));
8289                 return -1;
8290         }
8291
8292         fstrcpy(service_name, file_name);
8293
8294         if (asprintf(&fname, "%s/%s", dir_name, file_name) < 0) {
8295         }
8296
8297         /* Minimize the race condition by doing an lstat before we
8298            open and fstat. Ensure this isn't a symlink link. */
8299
8300         if (sys_lstat(fname, &lsbuf) != 0) {
8301                 DEBUG(0,("process_usershare_file: stat of %s failed. %s\n",
8302                         fname, strerror(errno) ));
8303                 SAFE_FREE(fname);
8304                 return -1;
8305         }
8306
8307         /* This must be a regular file, not a symlink, directory or
8308            other strange filetype. */
8309         if (!check_usershare_stat(fname, &lsbuf)) {
8310                 SAFE_FREE(fname);
8311                 return -1;
8312         }
8313
8314         {
8315                 char *canon_name = canonicalize_servicename(service_name);
8316                 TDB_DATA data = dbwrap_fetch_bystring(
8317                         ServiceHash, canon_name, canon_name);
8318
8319                 iService = -1;
8320
8321                 if ((data.dptr != NULL) && (data.dsize == sizeof(iService))) {
8322                         iService = *(int *)data.dptr;
8323                 }
8324                 TALLOC_FREE(canon_name);
8325         }
8326
8327         if (iService != -1 && ServicePtrs[iService]->usershare_last_mod == lsbuf.st_mtime) {
8328                 /* Nothing changed - Mark valid and return. */
8329                 DEBUG(10,("process_usershare_file: service %s not changed.\n",
8330                         service_name ));
8331                 ServicePtrs[iService]->usershare = USERSHARE_VALID;
8332                 SAFE_FREE(fname);
8333                 return iService;
8334         }
8335
8336         /* Try and open the file read only - no symlinks allowed. */
8337 #ifdef O_NOFOLLOW
8338         fd = sys_open(fname, O_RDONLY|O_NOFOLLOW, 0);
8339 #else
8340         fd = sys_open(fname, O_RDONLY, 0);
8341 #endif
8342
8343         if (fd == -1) {
8344                 DEBUG(0,("process_usershare_file: unable to open %s. %s\n",
8345                         fname, strerror(errno) ));
8346                 SAFE_FREE(fname);
8347                 return -1;
8348         }
8349
8350         /* Now fstat to be *SURE* it's a regular file. */
8351         if (sys_fstat(fd, &sbuf) != 0) {
8352                 close(fd);
8353                 DEBUG(0,("process_usershare_file: fstat of %s failed. %s\n",
8354                         fname, strerror(errno) ));
8355                 SAFE_FREE(fname);
8356                 return -1;
8357         }
8358
8359         /* Is it the same dev/inode as was lstated ? */
8360         if (lsbuf.st_dev != sbuf.st_dev || lsbuf.st_ino != sbuf.st_ino) {
8361                 close(fd);
8362                 DEBUG(0,("process_usershare_file: fstat of %s is a different file from lstat. "
8363                         "Symlink spoofing going on ?\n", fname ));
8364                 SAFE_FREE(fname);
8365                 return -1;
8366         }
8367
8368         /* This must be a regular file, not a symlink, directory or
8369            other strange filetype. */
8370         if (!check_usershare_stat(fname, &sbuf)) {
8371                 SAFE_FREE(fname);
8372                 return -1;
8373         }
8374
8375         lines = fd_lines_load(fd, &numlines, MAX_USERSHARE_FILE_SIZE, NULL);
8376
8377         close(fd);
8378         if (lines == NULL) {
8379                 DEBUG(0,("process_usershare_file: loading file %s owned by %u failed.\n",
8380                         fname, (unsigned int)sbuf.st_uid ));
8381                 SAFE_FREE(fname);
8382                 return -1;
8383         }
8384
8385         SAFE_FREE(fname);
8386
8387         /* Should we allow printers to be shared... ? */
8388         ctx = talloc_init("usershare_sd_xctx");
8389         if (!ctx) {
8390                 TALLOC_FREE(lines);
8391                 return 1;
8392         }
8393
8394         if (parse_usershare_file(ctx, &sbuf, service_name,
8395                         iService, lines, numlines, &sharepath,
8396                         &comment, &psd, &guest_ok) != USERSHARE_OK) {
8397                 talloc_destroy(ctx);
8398                 TALLOC_FREE(lines);
8399                 return -1;
8400         }
8401
8402         TALLOC_FREE(lines);
8403
8404         /* Everything ok - add the service possibly using a template. */
8405         if (iService < 0) {
8406                 const struct service *sp = &sDefault;
8407                 if (snum_template != -1) {
8408                         sp = ServicePtrs[snum_template];
8409                 }
8410
8411                 if ((iService = add_a_service(sp, service_name)) < 0) {
8412                         DEBUG(0, ("process_usershare_file: Failed to add "
8413                                 "new service %s\n", service_name));
8414                         talloc_destroy(ctx);
8415                         return -1;
8416                 }
8417
8418                 /* Read only is controlled by usershare ACL below. */
8419                 ServicePtrs[iService]->bRead_only = False;
8420         }
8421
8422         /* Write the ACL of the new/modified share. */
8423         if (!set_share_security(service_name, psd)) {
8424                  DEBUG(0, ("process_usershare_file: Failed to set share "
8425                         "security for user share %s\n",
8426                         service_name ));
8427                 lp_remove_service(iService);
8428                 talloc_destroy(ctx);
8429                 return -1;
8430         }
8431
8432         /* If from a template it may be marked invalid. */
8433         ServicePtrs[iService]->valid = True;
8434
8435         /* Set the service as a valid usershare. */
8436         ServicePtrs[iService]->usershare = USERSHARE_VALID;
8437
8438         /* Set guest access. */
8439         if (lp_usershare_allow_guests()) {
8440                 ServicePtrs[iService]->bGuest_ok = guest_ok;
8441         }
8442
8443         /* And note when it was loaded. */
8444         ServicePtrs[iService]->usershare_last_mod = sbuf.st_mtime;
8445         string_set(&ServicePtrs[iService]->szPath, sharepath);
8446         string_set(&ServicePtrs[iService]->comment, comment);
8447
8448         talloc_destroy(ctx);
8449
8450         return iService;
8451 }
8452
8453 /***************************************************************************
8454  Checks if a usershare entry has been modified since last load.
8455 ***************************************************************************/
8456
8457 static bool usershare_exists(int iService, time_t *last_mod)
8458 {
8459         SMB_STRUCT_STAT lsbuf;
8460         const char *usersharepath = Globals.szUsersharePath;
8461         char *fname;
8462
8463         if (asprintf(&fname, "%s/%s",
8464                                 usersharepath,
8465                                 ServicePtrs[iService]->szService) < 0) {
8466                 return false;
8467         }
8468
8469         if (sys_lstat(fname, &lsbuf) != 0) {
8470                 SAFE_FREE(fname);
8471                 return false;
8472         }
8473
8474         if (!S_ISREG(lsbuf.st_mode)) {
8475                 SAFE_FREE(fname);
8476                 return false;
8477         }
8478
8479         SAFE_FREE(fname);
8480         *last_mod = lsbuf.st_mtime;
8481         return true;
8482 }
8483
8484 /***************************************************************************
8485  Load a usershare service by name. Returns a valid servicenumber or -1.
8486 ***************************************************************************/
8487
8488 int load_usershare_service(const char *servicename)
8489 {
8490         SMB_STRUCT_STAT sbuf;
8491         const char *usersharepath = Globals.szUsersharePath;
8492         int max_user_shares = Globals.iUsershareMaxShares;
8493         int snum_template = -1;
8494
8495         if (*usersharepath == 0 ||  max_user_shares == 0) {
8496                 return -1;
8497         }
8498
8499         if (sys_stat(usersharepath, &sbuf) != 0) {
8500                 DEBUG(0,("load_usershare_service: stat of %s failed. %s\n",
8501                         usersharepath, strerror(errno) ));
8502                 return -1;
8503         }
8504
8505         if (!S_ISDIR(sbuf.st_mode)) {
8506                 DEBUG(0,("load_usershare_service: %s is not a directory.\n",
8507                         usersharepath ));
8508                 return -1;
8509         }
8510
8511         /*
8512          * This directory must be owned by root, and have the 't' bit set.
8513          * It also must not be writable by "other".
8514          */
8515
8516 #ifdef S_ISVTX
8517         if (sbuf.st_uid != 0 || !(sbuf.st_mode & S_ISVTX) || (sbuf.st_mode & S_IWOTH)) {
8518 #else
8519         if (sbuf.st_uid != 0 || (sbuf.st_mode & S_IWOTH)) {
8520 #endif
8521                 DEBUG(0,("load_usershare_service: directory %s is not owned by root "
8522                         "or does not have the sticky bit 't' set or is writable by anyone.\n",
8523                         usersharepath ));
8524                 return -1;
8525         }
8526
8527         /* Ensure the template share exists if it's set. */
8528         if (Globals.szUsershareTemplateShare[0]) {
8529                 /* We can't use lp_servicenumber here as we are recommending that
8530                    template shares have -valid=False set. */
8531                 for (snum_template = iNumServices - 1; snum_template >= 0; snum_template--) {
8532                         if (ServicePtrs[snum_template]->szService &&
8533                                         strequal(ServicePtrs[snum_template]->szService,
8534                                                 Globals.szUsershareTemplateShare)) {
8535                                 break;
8536                         }
8537                 }
8538
8539                 if (snum_template == -1) {
8540                         DEBUG(0,("load_usershare_service: usershare template share %s "
8541                                 "does not exist.\n",
8542                                 Globals.szUsershareTemplateShare ));
8543                         return -1;
8544                 }
8545         }
8546
8547         return process_usershare_file(usersharepath, servicename, snum_template);
8548 }
8549
8550 /***************************************************************************
8551  Load all user defined shares from the user share directory.
8552  We only do this if we're enumerating the share list.
8553  This is the function that can delete usershares that have
8554  been removed.
8555 ***************************************************************************/
8556
8557 int load_usershare_shares(void)
8558 {
8559         SMB_STRUCT_DIR *dp;
8560         SMB_STRUCT_STAT sbuf;
8561         SMB_STRUCT_DIRENT *de;
8562         int num_usershares = 0;
8563         int max_user_shares = Globals.iUsershareMaxShares;
8564         unsigned int num_dir_entries, num_bad_dir_entries, num_tmp_dir_entries;
8565         unsigned int allowed_bad_entries = ((2*max_user_shares)/10);
8566         unsigned int allowed_tmp_entries = ((2*max_user_shares)/10);
8567         int iService;
8568         int snum_template = -1;
8569         const char *usersharepath = Globals.szUsersharePath;
8570         int ret = lp_numservices();
8571
8572         if (max_user_shares == 0 || *usersharepath == '\0') {
8573                 return lp_numservices();
8574         }
8575
8576         if (sys_stat(usersharepath, &sbuf) != 0) {
8577                 DEBUG(0,("load_usershare_shares: stat of %s failed. %s\n",
8578                         usersharepath, strerror(errno) ));
8579                 return ret;
8580         }
8581
8582         /*
8583          * This directory must be owned by root, and have the 't' bit set.
8584          * It also must not be writable by "other".
8585          */
8586
8587 #ifdef S_ISVTX
8588         if (sbuf.st_uid != 0 || !(sbuf.st_mode & S_ISVTX) || (sbuf.st_mode & S_IWOTH)) {
8589 #else
8590         if (sbuf.st_uid != 0 || (sbuf.st_mode & S_IWOTH)) {
8591 #endif
8592                 DEBUG(0,("load_usershare_shares: directory %s is not owned by root "
8593                         "or does not have the sticky bit 't' set or is writable by anyone.\n",
8594                         usersharepath ));
8595                 return ret;
8596         }
8597
8598         /* Ensure the template share exists if it's set. */
8599         if (Globals.szUsershareTemplateShare[0]) {
8600                 /* We can't use lp_servicenumber here as we are recommending that
8601                    template shares have -valid=False set. */
8602                 for (snum_template = iNumServices - 1; snum_template >= 0; snum_template--) {
8603                         if (ServicePtrs[snum_template]->szService &&
8604                                         strequal(ServicePtrs[snum_template]->szService,
8605                                                 Globals.szUsershareTemplateShare)) {
8606                                 break;
8607                         }
8608                 }
8609
8610                 if (snum_template == -1) {
8611                         DEBUG(0,("load_usershare_shares: usershare template share %s "
8612                                 "does not exist.\n",
8613                                 Globals.szUsershareTemplateShare ));
8614                         return ret;
8615                 }
8616         }
8617
8618         /* Mark all existing usershares as pending delete. */
8619         for (iService = iNumServices - 1; iService >= 0; iService--) {
8620                 if (VALID(iService) && ServicePtrs[iService]->usershare) {
8621                         ServicePtrs[iService]->usershare = USERSHARE_PENDING_DELETE;
8622                 }
8623         }
8624
8625         dp = sys_opendir(usersharepath);
8626         if (!dp) {
8627                 DEBUG(0,("load_usershare_shares:: failed to open directory %s. %s\n",
8628                         usersharepath, strerror(errno) ));
8629                 return ret;
8630         }
8631
8632         for (num_dir_entries = 0, num_bad_dir_entries = 0, num_tmp_dir_entries = 0;
8633                         (de = sys_readdir(dp));
8634                         num_dir_entries++ ) {
8635                 int r;
8636                 const char *n = de->d_name;
8637
8638                 /* Ignore . and .. */
8639                 if (*n == '.') {
8640                         if ((n[1] == '\0') || (n[1] == '.' && n[2] == '\0')) {
8641                                 continue;
8642                         }
8643                 }
8644
8645                 if (n[0] == ':') {
8646                         /* Temporary file used when creating a share. */
8647                         num_tmp_dir_entries++;
8648                 }
8649
8650                 /* Allow 20% tmp entries. */
8651                 if (num_tmp_dir_entries > allowed_tmp_entries) {
8652                         DEBUG(0,("load_usershare_shares: too many temp entries (%u) "
8653                                 "in directory %s\n",
8654                                 num_tmp_dir_entries, usersharepath));
8655                         break;
8656                 }
8657
8658                 r = process_usershare_file(usersharepath, n, snum_template);
8659                 if (r == 0) {
8660                         /* Update the services count. */
8661                         num_usershares++;
8662                         if (num_usershares >= max_user_shares) {
8663                                 DEBUG(0,("load_usershare_shares: max user shares reached "
8664                                         "on file %s in directory %s\n",
8665                                         n, usersharepath ));
8666                                 break;
8667                         }
8668                 } else if (r == -1) {
8669                         num_bad_dir_entries++;
8670                 }
8671
8672                 /* Allow 20% bad entries. */
8673                 if (num_bad_dir_entries > allowed_bad_entries) {
8674                         DEBUG(0,("load_usershare_shares: too many bad entries (%u) "
8675                                 "in directory %s\n",
8676                                 num_bad_dir_entries, usersharepath));
8677                         break;
8678                 }
8679
8680                 /* Allow 20% bad entries. */
8681                 if (num_dir_entries > max_user_shares + allowed_bad_entries) {
8682                         DEBUG(0,("load_usershare_shares: too many total entries (%u) "
8683                         "in directory %s\n",
8684                         num_dir_entries, usersharepath));
8685                         break;
8686                 }
8687         }
8688
8689         sys_closedir(dp);
8690
8691         /* Sweep through and delete any non-refreshed usershares that are
8692            not currently in use. */
8693         for (iService = iNumServices - 1; iService >= 0; iService--) {
8694                 if (VALID(iService) && (ServicePtrs[iService]->usershare == USERSHARE_PENDING_DELETE)) {
8695                         if (conn_snum_used(iService)) {
8696                                 continue;
8697                         }
8698                         /* Remove from the share ACL db. */
8699                         DEBUG(10,("load_usershare_shares: Removing deleted usershare %s\n",
8700                                 lp_servicename(iService) ));
8701                         delete_share_security(lp_servicename(iService));
8702                         free_service_byindex(iService);
8703                 }
8704         }
8705
8706         return lp_numservices();
8707 }
8708
8709 /********************************************************
8710  Destroy global resources allocated in this file
8711 ********************************************************/
8712
8713 void gfree_loadparm(void)
8714 {
8715         struct file_lists *f;
8716         struct file_lists *next;
8717         int i;
8718
8719         /* Free the file lists */
8720
8721         f = file_lists;
8722         while( f ) {
8723                 next = f->next;
8724                 SAFE_FREE( f->name );
8725                 SAFE_FREE( f->subfname );
8726                 SAFE_FREE( f );
8727                 f = next;
8728         }
8729         file_lists = NULL;
8730
8731         /* Free resources allocated to services */
8732
8733         for ( i = 0; i < iNumServices; i++ ) {
8734                 if ( VALID(i) ) {
8735                         free_service_byindex(i);
8736                 }
8737         }
8738
8739         SAFE_FREE( ServicePtrs );
8740         iNumServices = 0;
8741
8742         /* Now release all resources allocated to global
8743            parameters and the default service */
8744
8745         free_global_parameters();
8746 }
8747
8748
8749 /***************************************************************************
8750  Allow client apps to specify that they are a client
8751 ***************************************************************************/
8752 void lp_set_in_client(bool b)
8753 {
8754     in_client = b;
8755 }
8756
8757
8758 /***************************************************************************
8759  Determine if we're running in a client app
8760 ***************************************************************************/
8761 bool lp_is_in_client(void)
8762 {
8763     return in_client;
8764 }
8765
8766 /***************************************************************************
8767  Load the services array from the services file. Return True on success, 
8768  False on failure.
8769 ***************************************************************************/
8770
8771 bool lp_load_ex(const char *pszFname,
8772                 bool global_only,
8773                 bool save_defaults,
8774                 bool add_ipc,
8775                 bool initialize_globals,
8776                 bool allow_include_registry,
8777                 bool allow_registry_shares)
8778 {
8779         char *n2 = NULL;
8780         bool bRetval;
8781
8782         bRetval = False;
8783
8784         DEBUG(3, ("lp_load_ex: refreshing parameters\n"));
8785
8786         bInGlobalSection = True;
8787         bGlobalOnly = global_only;
8788         bAllowIncludeRegistry = allow_include_registry;
8789
8790         init_globals(! initialize_globals);
8791         debug_init();
8792
8793         if (save_defaults) {
8794                 init_locals();
8795                 lp_save_defaults();
8796         }
8797
8798         free_param_opts(&Globals.param_opt);
8799
8800         /* We get sections first, so have to start 'behind' to make up */
8801         iServiceIndex = -1;
8802
8803         if (lp_config_backend_is_file()) {
8804                 n2 = alloc_sub_basic(get_current_username(),
8805                                         current_user_info.domain,
8806                                         pszFname);
8807                 if (!n2) {
8808                         smb_panic("lp_load_ex: out of memory");
8809                 }
8810
8811                 add_to_file_list(pszFname, n2);
8812
8813                 bRetval = pm_process(n2, do_section, do_parameter, NULL);
8814                 SAFE_FREE(n2);
8815
8816                 /* finish up the last section */
8817                 DEBUG(4, ("pm_process() returned %s\n", BOOLSTR(bRetval)));
8818                 if (bRetval) {
8819                         if (iServiceIndex >= 0) {
8820                                 bRetval = service_ok(iServiceIndex);
8821                         }
8822                 }
8823
8824                 if (lp_config_backend_is_registry()) {
8825                         /* config backend changed to registry in config file */
8826                         /*
8827                          * We need to use this extra global variable here to
8828                          * survive restart: init_globals uses this as a default
8829                          * for ConfigBackend. Otherwise, init_globals would
8830                          *  send us into an endless loop here.
8831                          */
8832                         config_backend = CONFIG_BACKEND_REGISTRY;
8833                         /* start over */
8834                         DEBUG(1, ("lp_load_ex: changing to config backend "
8835                                   "registry\n"));
8836                         init_globals(false);
8837                         lp_kill_all_services();
8838                         return lp_load_ex(pszFname, global_only, save_defaults,
8839                                           add_ipc, initialize_globals,
8840                                           allow_include_registry,
8841                                           allow_registry_shares);
8842                 }
8843         } else if (lp_config_backend_is_registry()) {
8844                 bRetval = process_registry_globals();
8845         } else {
8846                 DEBUG(0, ("Illegal config  backend given: %d\n",
8847                           lp_config_backend()));
8848                 bRetval = false;
8849         }
8850
8851         if (bRetval && lp_registry_shares() && allow_registry_shares) {
8852                 bRetval = process_registry_shares();
8853         }
8854
8855         lp_add_auto_services(lp_auto_services());
8856
8857         if (add_ipc) {
8858                 /* When 'restrict anonymous = 2' guest connections to ipc$
8859                    are denied */
8860                 lp_add_ipc("IPC$", (lp_restrict_anonymous() < 2));
8861                 if ( lp_enable_asu_support() ) {
8862                         lp_add_ipc("ADMIN$", false);
8863                 }
8864         }
8865
8866         set_server_role();
8867         set_default_server_announce_type();
8868         set_allowed_client_auth();
8869
8870         bLoaded = True;
8871
8872         /* Now we check bWINSsupport and set szWINSserver to 127.0.0.1 */
8873         /* if bWINSsupport is true and we are in the client            */
8874         if (lp_is_in_client() && Globals.bWINSsupport) {
8875                 lp_do_parameter(GLOBAL_SECTION_SNUM, "wins server", "127.0.0.1");
8876         }
8877
8878         init_iconv();
8879
8880         bAllowIncludeRegistry = true;
8881
8882         return (bRetval);
8883 }
8884
8885 bool lp_load(const char *pszFname,
8886              bool global_only,
8887              bool save_defaults,
8888              bool add_ipc,
8889              bool initialize_globals)
8890 {
8891         return lp_load_ex(pszFname,
8892                           global_only,
8893                           save_defaults,
8894                           add_ipc,
8895                           initialize_globals,
8896                           true, false);
8897 }
8898
8899 bool lp_load_initial_only(const char *pszFname)
8900 {
8901         return lp_load_ex(pszFname,
8902                           true,
8903                           false,
8904                           false,
8905                           true,
8906                           false,
8907                           false);
8908 }
8909
8910 bool lp_load_with_registry_shares(const char *pszFname,
8911                                   bool global_only,
8912                                   bool save_defaults,
8913                                   bool add_ipc,
8914                                   bool initialize_globals)
8915 {
8916         return lp_load_ex(pszFname,
8917                           global_only,
8918                           save_defaults,
8919                           add_ipc,
8920                           initialize_globals,
8921                           true,
8922                           true);
8923 }
8924
8925 /***************************************************************************
8926  Return the max number of services.
8927 ***************************************************************************/
8928
8929 int lp_numservices(void)
8930 {
8931         return (iNumServices);
8932 }
8933
8934 /***************************************************************************
8935 Display the contents of the services array in human-readable form.
8936 ***************************************************************************/
8937
8938 void lp_dump(FILE *f, bool show_defaults, int maxtoprint)
8939 {
8940         int iService;
8941
8942         if (show_defaults)
8943                 defaults_saved = False;
8944
8945         dump_globals(f);
8946
8947         dump_a_service(&sDefault, f);
8948
8949         for (iService = 0; iService < maxtoprint; iService++) {
8950                 fprintf(f,"\n");
8951                 lp_dump_one(f, show_defaults, iService);
8952         }
8953 }
8954
8955 /***************************************************************************
8956 Display the contents of one service in human-readable form.
8957 ***************************************************************************/
8958
8959 void lp_dump_one(FILE * f, bool show_defaults, int snum)
8960 {
8961         if (VALID(snum)) {
8962                 if (ServicePtrs[snum]->szService[0] == '\0')
8963                         return;
8964                 dump_a_service(ServicePtrs[snum], f);
8965         }
8966 }
8967
8968 /***************************************************************************
8969 Return the number of the service with the given name, or -1 if it doesn't
8970 exist. Note that this is a DIFFERENT ANIMAL from the internal function
8971 getservicebyname()! This works ONLY if all services have been loaded, and
8972 does not copy the found service.
8973 ***************************************************************************/
8974
8975 int lp_servicenumber(const char *pszServiceName)
8976 {
8977         int iService;
8978         fstring serviceName;
8979         
8980         if (!pszServiceName) {
8981                 return GLOBAL_SECTION_SNUM;
8982         }
8983         
8984         for (iService = iNumServices - 1; iService >= 0; iService--) {
8985                 if (VALID(iService) && ServicePtrs[iService]->szService) {
8986                         /*
8987                          * The substitution here is used to support %U is
8988                          * service names
8989                          */
8990                         fstrcpy(serviceName, ServicePtrs[iService]->szService);
8991                         standard_sub_basic(get_current_username(),
8992                                            current_user_info.domain,
8993                                            serviceName,sizeof(serviceName));
8994                         if (strequal(serviceName, pszServiceName)) {
8995                                 break;
8996                         }
8997                 }
8998         }
8999
9000         if (iService >= 0 && ServicePtrs[iService]->usershare == USERSHARE_VALID) {
9001                 time_t last_mod;
9002
9003                 if (!usershare_exists(iService, &last_mod)) {
9004                         /* Remove the share security tdb entry for it. */
9005                         delete_share_security(lp_servicename(iService));
9006                         /* Remove it from the array. */
9007                         free_service_byindex(iService);
9008                         /* Doesn't exist anymore. */
9009                         return GLOBAL_SECTION_SNUM;
9010                 }
9011
9012                 /* Has it been modified ? If so delete and reload. */
9013                 if (ServicePtrs[iService]->usershare_last_mod < last_mod) {
9014                         /* Remove it from the array. */
9015                         free_service_byindex(iService);
9016                         /* and now reload it. */
9017                         iService = load_usershare_service(pszServiceName);
9018                 }
9019         }
9020
9021         if (iService < 0) {
9022                 DEBUG(7,("lp_servicenumber: couldn't find %s\n", pszServiceName));
9023                 return GLOBAL_SECTION_SNUM;
9024         }
9025
9026         return (iService);
9027 }
9028
9029 bool share_defined(const char *service_name)
9030 {
9031         return (lp_servicenumber(service_name) != -1);
9032 }
9033
9034 struct share_params *get_share_params(TALLOC_CTX *mem_ctx,
9035                                       const char *sharename)
9036 {
9037         struct share_params *result;
9038         char *sname;
9039         int snum;
9040
9041         if (!(sname = SMB_STRDUP(sharename))) {
9042                 return NULL;
9043         }
9044
9045         snum = find_service(sname);
9046         SAFE_FREE(sname);
9047
9048         if (snum < 0) {
9049                 return NULL;
9050         }
9051
9052         if (!(result = TALLOC_P(mem_ctx, struct share_params))) {
9053                 DEBUG(0, ("talloc failed\n"));
9054                 return NULL;
9055         }
9056
9057         result->service = snum;
9058         return result;
9059 }
9060
9061 struct share_iterator *share_list_all(TALLOC_CTX *mem_ctx)
9062 {
9063         struct share_iterator *result;
9064
9065         if (!(result = TALLOC_P(mem_ctx, struct share_iterator))) {
9066                 DEBUG(0, ("talloc failed\n"));
9067                 return NULL;
9068         }
9069
9070         result->next_id = 0;
9071         return result;
9072 }
9073
9074 struct share_params *next_share(struct share_iterator *list)
9075 {
9076         struct share_params *result;
9077
9078         while (!lp_snum_ok(list->next_id) &&
9079                (list->next_id < lp_numservices())) {
9080                 list->next_id += 1;
9081         }
9082
9083         if (list->next_id >= lp_numservices()) {
9084                 return NULL;
9085         }
9086
9087         if (!(result = TALLOC_P(list, struct share_params))) {
9088                 DEBUG(0, ("talloc failed\n"));
9089                 return NULL;
9090         }
9091
9092         result->service = list->next_id;
9093         list->next_id += 1;
9094         return result;
9095 }
9096
9097 struct share_params *next_printer(struct share_iterator *list)
9098 {
9099         struct share_params *result;
9100
9101         while ((result = next_share(list)) != NULL) {
9102                 if (lp_print_ok(result->service)) {
9103                         break;
9104                 }
9105         }
9106         return result;
9107 }
9108
9109 /*
9110  * This is a hack for a transition period until we transformed all code from
9111  * service numbers to struct share_params.
9112  */
9113
9114 struct share_params *snum2params_static(int snum)
9115 {
9116         static struct share_params result;
9117         result.service = snum;
9118         return &result;
9119 }
9120
9121 /*******************************************************************
9122  A useful volume label function. 
9123 ********************************************************************/
9124
9125 const char *volume_label(int snum)
9126 {
9127         char *ret;
9128         const char *label = lp_volume(snum);
9129         if (!*label) {
9130                 label = lp_servicename(snum);
9131         }
9132                 
9133         /* This returns a 33 byte guarenteed null terminated string. */
9134         ret = talloc_strndup(talloc_tos(), label, 32);
9135         if (!ret) {
9136                 return "";
9137         }               
9138         return ret;
9139 }
9140
9141 /*******************************************************************
9142  Set the server type we will announce as via nmbd.
9143 ********************************************************************/
9144
9145 static void set_default_server_announce_type(void)
9146 {
9147         default_server_announce = 0;
9148         default_server_announce |= SV_TYPE_WORKSTATION;
9149         default_server_announce |= SV_TYPE_SERVER;
9150         default_server_announce |= SV_TYPE_SERVER_UNIX;
9151
9152         /* note that the flag should be set only if we have a 
9153            printer service but nmbd doesn't actually load the 
9154            services so we can't tell   --jerry */
9155
9156         default_server_announce |= SV_TYPE_PRINTQ_SERVER;
9157
9158         switch (lp_announce_as()) {
9159                 case ANNOUNCE_AS_NT_SERVER:
9160                         default_server_announce |= SV_TYPE_SERVER_NT;
9161                         /* fall through... */
9162                 case ANNOUNCE_AS_NT_WORKSTATION:
9163                         default_server_announce |= SV_TYPE_NT;
9164                         break;
9165                 case ANNOUNCE_AS_WIN95:
9166                         default_server_announce |= SV_TYPE_WIN95_PLUS;
9167                         break;
9168                 case ANNOUNCE_AS_WFW:
9169                         default_server_announce |= SV_TYPE_WFW;
9170                         break;
9171                 default:
9172                         break;
9173         }
9174
9175         switch (lp_server_role()) {
9176                 case ROLE_DOMAIN_MEMBER:
9177                         default_server_announce |= SV_TYPE_DOMAIN_MEMBER;
9178                         break;
9179                 case ROLE_DOMAIN_PDC:
9180                         default_server_announce |= SV_TYPE_DOMAIN_CTRL;
9181                         break;
9182                 case ROLE_DOMAIN_BDC:
9183                         default_server_announce |= SV_TYPE_DOMAIN_BAKCTRL;
9184                         break;
9185                 case ROLE_STANDALONE:
9186                 default:
9187                         break;
9188         }
9189         if (lp_time_server())
9190                 default_server_announce |= SV_TYPE_TIME_SOURCE;
9191
9192         if (lp_host_msdfs())
9193                 default_server_announce |= SV_TYPE_DFS_SERVER;
9194 }
9195
9196 /***********************************************************
9197  returns role of Samba server
9198 ************************************************************/
9199
9200 int lp_server_role(void)
9201 {
9202         return server_role;
9203 }
9204
9205 /***********************************************************
9206  If we are PDC then prefer us as DMB
9207 ************************************************************/
9208
9209 bool lp_domain_master(void)
9210 {
9211         if (Globals.iDomainMaster == Auto)
9212                 return (lp_server_role() == ROLE_DOMAIN_PDC);
9213
9214         return (bool)Globals.iDomainMaster;
9215 }
9216
9217 /***********************************************************
9218  If we are DMB then prefer us as LMB
9219 ************************************************************/
9220
9221 bool lp_preferred_master(void)
9222 {
9223         if (Globals.iPreferredMaster == Auto)
9224                 return (lp_local_master() && lp_domain_master());
9225
9226         return (bool)Globals.iPreferredMaster;
9227 }
9228
9229 /*******************************************************************
9230  Remove a service.
9231 ********************************************************************/
9232
9233 void lp_remove_service(int snum)
9234 {
9235         ServicePtrs[snum]->valid = False;
9236         invalid_services[num_invalid_services++] = snum;
9237 }
9238
9239 /*******************************************************************
9240  Copy a service.
9241 ********************************************************************/
9242
9243 void lp_copy_service(int snum, const char *new_name)
9244 {
9245         do_section(new_name, NULL);
9246         if (snum >= 0) {
9247                 snum = lp_servicenumber(new_name);
9248                 if (snum >= 0)
9249                         lp_do_parameter(snum, "copy", lp_servicename(snum));
9250         }
9251 }
9252
9253
9254 /*******************************************************************
9255  Get the default server type we will announce as via nmbd.
9256 ********************************************************************/
9257
9258 int lp_default_server_announce(void)
9259 {
9260         return default_server_announce;
9261 }
9262
9263 /*******************************************************************
9264  Split the announce version into major and minor numbers.
9265 ********************************************************************/
9266
9267 int lp_major_announce_version(void)
9268 {
9269         static bool got_major = False;
9270         static int major_version = DEFAULT_MAJOR_VERSION;
9271         char *vers;
9272         char *p;
9273
9274         if (got_major)
9275                 return major_version;
9276
9277         got_major = True;
9278         if ((vers = lp_announce_version()) == NULL)
9279                 return major_version;
9280
9281         if ((p = strchr_m(vers, '.')) == 0)
9282                 return major_version;
9283
9284         *p = '\0';
9285         major_version = atoi(vers);
9286         return major_version;
9287 }
9288
9289 int lp_minor_announce_version(void)
9290 {
9291         static bool got_minor = False;
9292         static int minor_version = DEFAULT_MINOR_VERSION;
9293         char *vers;
9294         char *p;
9295
9296         if (got_minor)
9297                 return minor_version;
9298
9299         got_minor = True;
9300         if ((vers = lp_announce_version()) == NULL)
9301                 return minor_version;
9302
9303         if ((p = strchr_m(vers, '.')) == 0)
9304                 return minor_version;
9305
9306         p++;
9307         minor_version = atoi(p);
9308         return minor_version;
9309 }
9310
9311 /***********************************************************
9312  Set the global name resolution order (used in smbclient).
9313 ************************************************************/
9314
9315 void lp_set_name_resolve_order(const char *new_order)
9316 {
9317         string_set(&Globals.szNameResolveOrder, new_order);
9318 }
9319
9320 const char *lp_printername(int snum)
9321 {
9322         const char *ret = _lp_printername(snum);
9323         if (ret == NULL || (ret != NULL && *ret == '\0'))
9324                 ret = lp_const_servicename(snum);
9325
9326         return ret;
9327 }
9328
9329
9330 /***********************************************************
9331  Allow daemons such as winbindd to fix their logfile name.
9332 ************************************************************/
9333
9334 void lp_set_logfile(const char *name)
9335 {
9336         string_set(&Globals.szLogFile, name);
9337         debug_set_logfile(name);
9338 }
9339
9340 /*******************************************************************
9341  Return the max print jobs per queue.
9342 ********************************************************************/
9343
9344 int lp_maxprintjobs(int snum)
9345 {
9346         int maxjobs = LP_SNUM_OK(snum) ? ServicePtrs[snum]->iMaxPrintJobs : sDefault.iMaxPrintJobs;
9347         if (maxjobs <= 0 || maxjobs >= PRINT_MAX_JOBID)
9348                 maxjobs = PRINT_MAX_JOBID - 1;
9349
9350         return maxjobs;
9351 }
9352
9353 const char *lp_printcapname(void)
9354 {
9355         if ((Globals.szPrintcapname != NULL) &&
9356             (Globals.szPrintcapname[0] != '\0'))
9357                 return Globals.szPrintcapname;
9358
9359         if (sDefault.iPrinting == PRINT_CUPS) {
9360 #ifdef HAVE_CUPS
9361                 return "cups";
9362 #else
9363                 return "lpstat";
9364 #endif
9365         }
9366
9367         if (sDefault.iPrinting == PRINT_BSD)
9368                 return "/etc/printcap";
9369
9370         return PRINTCAP_NAME;
9371 }
9372
9373 /*******************************************************************
9374  Ensure we don't use sendfile if server smb signing is active.
9375 ********************************************************************/
9376
9377 static uint32 spoolss_state;
9378
9379 bool lp_disable_spoolss( void )
9380 {
9381         if ( spoolss_state == SVCCTL_STATE_UNKNOWN )
9382                 spoolss_state = _lp_disable_spoolss() ? SVCCTL_STOPPED : SVCCTL_RUNNING;
9383
9384         return spoolss_state == SVCCTL_STOPPED ? True : False;
9385 }
9386
9387 void lp_set_spoolss_state( uint32 state )
9388 {
9389         SMB_ASSERT( (state == SVCCTL_STOPPED) || (state == SVCCTL_RUNNING) );
9390
9391         spoolss_state = state;
9392 }
9393
9394 uint32 lp_get_spoolss_state( void )
9395 {
9396         return lp_disable_spoolss() ? SVCCTL_STOPPED : SVCCTL_RUNNING;
9397 }
9398
9399 /*******************************************************************
9400  Ensure we don't use sendfile if server smb signing is active.
9401 ********************************************************************/
9402
9403 bool lp_use_sendfile(int snum)
9404 {
9405         /* Using sendfile blows the brains out of any DOS or Win9x TCP stack... JRA. */
9406         if (Protocol < PROTOCOL_NT1) {
9407                 return False;
9408         }
9409         return (_lp_use_sendfile(snum) &&
9410                         (get_remote_arch() != RA_WIN95) &&
9411                         !srv_is_signing_active());
9412 }
9413
9414 /*******************************************************************
9415  Turn off sendfile if we find the underlying OS doesn't support it.
9416 ********************************************************************/
9417
9418 void set_use_sendfile(int snum, bool val)
9419 {
9420         if (LP_SNUM_OK(snum))
9421                 ServicePtrs[snum]->bUseSendfile = val;
9422         else
9423                 sDefault.bUseSendfile = val;
9424 }
9425
9426 /*******************************************************************
9427  Turn off storing DOS attributes if this share doesn't support it.
9428 ********************************************************************/
9429
9430 void set_store_dos_attributes(int snum, bool val)
9431 {
9432         if (!LP_SNUM_OK(snum))
9433                 return;
9434         ServicePtrs[(snum)]->bStoreDosAttributes = val;
9435 }
9436
9437 void lp_set_mangling_method(const char *new_method)
9438 {
9439         string_set(&Globals.szManglingMethod, new_method);
9440 }
9441
9442 /*******************************************************************
9443  Global state for POSIX pathname processing.
9444 ********************************************************************/
9445
9446 static bool posix_pathnames;
9447
9448 bool lp_posix_pathnames(void)
9449 {
9450         return posix_pathnames;
9451 }
9452
9453 /*******************************************************************
9454  Change everything needed to ensure POSIX pathname processing (currently
9455  not much).
9456 ********************************************************************/
9457
9458 void lp_set_posix_pathnames(void)
9459 {
9460         posix_pathnames = True;
9461 }
9462
9463 /*******************************************************************
9464  Global state for POSIX lock processing - CIFS unix extensions.
9465 ********************************************************************/
9466
9467 bool posix_default_lock_was_set;
9468 static enum brl_flavour posix_cifsx_locktype; /* By default 0 == WINDOWS_LOCK */
9469
9470 enum brl_flavour lp_posix_cifsu_locktype(files_struct *fsp)
9471 {
9472         if (posix_default_lock_was_set) {
9473                 return posix_cifsx_locktype;
9474         } else {
9475                 return fsp->posix_open ? POSIX_LOCK : WINDOWS_LOCK;
9476         }
9477 }
9478
9479 /*******************************************************************
9480 ********************************************************************/
9481
9482 void lp_set_posix_default_cifsx_readwrite_locktype(enum brl_flavour val)
9483 {
9484         posix_default_lock_was_set = True;
9485         posix_cifsx_locktype = val;
9486 }
9487
9488 int lp_min_receive_file_size(void)
9489 {
9490         if (Globals.iminreceivefile < 0) {
9491                 return 0;
9492         }
9493         return MIN(Globals.iminreceivefile, BUFFER_SIZE);
9494 }
9495
9496 /*******************************************************************
9497  If socket address is an empty character string, it is necessary to 
9498  define it as "0.0.0.0". 
9499 ********************************************************************/
9500
9501 const char *lp_socket_address(void)
9502 {
9503         char *sock_addr = Globals.szSocketAddress;
9504         
9505         if (sock_addr[0] == '\0'){
9506                 string_set(&Globals.szSocketAddress, "0.0.0.0");
9507         }
9508         return  Globals.szSocketAddress;
9509 }