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