r7008: - split out the loadparm type definitions so loadparm internals can be accesse...
[samba.git] / source4 / 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) James Myers 2003 <myersjj@samba.org>
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 2 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, write to the Free Software
26    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 */
28
29 /*
30  *  Load parameters.
31  *
32  *  This module provides suitable callback functions for the params
33  *  module. It builds the internal table of service details which is
34  *  then used by the rest of the server.
35  *
36  * To add a parameter:
37  *
38  * 1) add it to the global or service structure definition
39  * 2) add it to the parm_table
40  * 3) add it to the list of available functions (eg: using FN_GLOBAL_STRING())
41  * 4) If it's a global then initialise it in init_globals. If a local
42  *    (ie. service) parameter then initialise it in the sDefault structure
43  *  
44  *
45  * Notes:
46  *   The configuration file is processed sequentially for speed. It is NOT
47  *   accessed randomly as happens in 'real' Windows. For this reason, there
48  *   is a fair bit of sequence-dependent code here - ie., code which assumes
49  *   that certain things happen before others. In particular, the code which
50  *   happens at the boundary between sections is delicately poised, so be
51  *   careful!
52  *
53  */
54
55 #include "includes.h"
56 #include "version.h"
57 #include "dynconfig.h"
58 #include "system/time.h"
59 #include "system/iconv.h"
60 #include "system/network.h"
61 #include "system/printing.h"
62 #include "librpc/gen_ndr/ndr_svcctl.h"
63 #include "librpc/gen_ndr/ndr_samr.h"
64 #include "librpc/gen_ndr/ndr_nbt.h"
65 #include "dlinklist.h"
66 #include "param/loadparm.h"
67
68 BOOL in_client = False;         /* Not in the client by default */
69 static BOOL bLoaded = False;
70
71 #ifndef GLOBAL_NAME
72 #define GLOBAL_NAME "global"
73 #endif
74
75 #ifndef PRINTERS_NAME
76 #define PRINTERS_NAME "printers"
77 #endif
78
79 #ifndef HOMES_NAME
80 #define HOMES_NAME "homes"
81 #endif
82
83 /* some helpful bits */
84 #define LP_SNUM_OK(i) (((i) >= 0) && ((i) < iNumServices) && ServicePtrs[(i)]->valid)
85 #define VALID(i) ServicePtrs[i]->valid
86
87 static BOOL do_parameter(const char *, const char *);
88 static BOOL do_parameter_var(const char *pszParmName, const char *fmt, ...);
89
90 static BOOL defaults_saved = False;
91
92
93 #define FLAG_BASIC      0x0001 /* fundamental options */
94 #define FLAG_SHARE      0x0002 /* file sharing options */
95 #define FLAG_PRINT      0x0004 /* printing options */
96 #define FLAG_GLOBAL     0x0008 /* local options that should be globally settable in SWAT */
97 #define FLAG_WIZARD     0x0010 /* Parameters that the wizard will operate on */
98 #define FLAG_ADVANCED   0x0020 /* Parameters that the wizard will operate on */
99 #define FLAG_DEVELOPER  0x0040 /* Parameters that the wizard will operate on */
100 #define FLAG_DEPRECATED 0x1000 /* options that should no longer be used */
101 #define FLAG_HIDE       0x2000 /* options that should be hidden in SWAT */
102 #define FLAG_DOS_STRING 0x4000 /* convert from UNIX to DOS codepage when reading this string. */
103 #define FLAG_CMDLINE    0x8000 /* this option was set from the command line */
104
105
106
107
108 struct param_opt {
109         struct param_opt *prev, *next;
110         char *key;
111         char *value;
112         int flags;
113 };
114
115 /* 
116  * This structure describes global (ie., server-wide) parameters.
117  */
118 typedef struct
119 {
120         char **smb_ports;
121         char *dos_charset;
122         char *unix_charset;
123         char *ncalrpc_dir;
124         char *display_charset;
125         char *szPrintcapname;
126         char *szLockDir;
127         char *szPidDir;
128         char *szRootdir;
129         char *szDefaultService;
130         char *szHostsEquiv;
131         char *szServerString;
132         char *szAutoServices;
133         char *szPasswdProgram;
134         char *szPasswdChat;
135         char *szLogFile;
136         char *szConfigFile;
137         char *szSMBPasswdFile;
138         char *szSAM_URL;
139         char *szSPOOLSS_URL;
140         char *szWINS_URL;
141         char *szPrivateDir;
142         char **szPreloadModules;
143         char **szPasswordServers;
144         char *szSocketOptions;
145         char *szRealm;
146         char *szADSserver;
147         char *szLogonScript;
148         char *szLogonPath;
149         char *szLogonDrive;
150         char *szLogonHome;
151         char **szWINSservers;
152         char **szInterfaces;
153         char *szRemoteAnnounce;
154         char *szRemoteBrowseSync;
155         char *szSocketAddress;
156         char *szAnnounceVersion;        /* This is initialised in init_globals */
157         char *szWorkgroup;
158         char *szNetbiosName;
159         char **szNetbiosAliases;
160         char *szNetbiosScope;
161         char *szDomainOtherSIDs;
162         char **szNameResolveOrder;
163         char *szPanicAction;
164         char *szAddUserScript; 
165         char *szAddMachineScript;
166         char *szWINSHook;
167         char *szWINSPartners;
168         char **dcerpc_ep_servers;
169         char **server_services;
170         char *szWinbindUID;
171         char *szWinbindGID;
172         char *szNonUnixAccountRange;
173         char *szTemplateHomedir;
174         char *szTemplateShell;
175         char *szWinbindSeparator;
176         BOOL bWinbindEnumUsers;
177         BOOL bWinbindEnumGroups;
178         BOOL bWinbindUseDefaultDomain;
179         char *szIDMapBackend;
180         char *szGuestaccount;
181         char *swat_directory;
182         int max_mux;
183         int max_xmit;
184         int pwordlevel;
185         int unamelevel;
186         int maxprotocol;
187         int minprotocol;
188         int security;
189         char **AuthMethods;
190         BOOL paranoid_server_security;
191         int lpqcachetime;
192         BOOL bDisableSpoolss;
193         int os_level;
194         int enhanced_browsing;
195         int time_offset;
196         int max_ttl;
197         int max_wins_ttl;
198         int min_wins_ttl;
199         int lm_announce;
200         int lm_interval;
201         int announce_as;        /* This is initialised in init_globals */
202         int machine_password_timeout;
203         int winbind_cache_time;
204         int iLockSpinCount;
205         int iLockSpinTime;
206         int nbt_port;
207         int dgram_port;
208         int cldap_port;
209         int web_port;
210         char *socket_options;
211         BOOL bDNSproxy;
212         BOOL bWINSsupport;
213         BOOL bWINSproxy;
214         BOOL bLocalMaster;
215         BOOL bPreferredMaster;
216         BOOL bDomainMaster;
217         BOOL bDomainLogons;
218         BOOL bEncryptPasswords;
219         BOOL bNullPasswords;
220         BOOL bObeyPamRestrictions;
221         BOOL bLoadPrinters;
222         BOOL bLargeReadwrite;
223         BOOL bReadRaw;
224         BOOL bWriteRaw;
225         BOOL bTimeServer;
226         BOOL bBindInterfacesOnly;
227         BOOL bPamPasswordChange;
228         BOOL bNTSmbSupport;
229         BOOL bNTStatusSupport;
230         BOOL bAllowTrustedDomains;
231         BOOL bLanmanAuth;
232         BOOL bNTLMAuth;
233         BOOL bUseSpnego;
234         int  server_signing;
235         int  client_signing;
236         BOOL bClientLanManAuth;
237         BOOL bClientNTLMv2Auth;
238         BOOL bHostMSDfs;
239         BOOL bHideLocalUsers;
240         BOOL bUnicode;
241         BOOL bUseMmap;
242         BOOL bHostnameLookups;
243         BOOL bUnixExtensions;
244         BOOL bDisableNetbios;
245         BOOL bRpcBigEndian;
246         int restrict_anonymous;
247         int name_cache_timeout;
248         struct param_opt *param_opt;
249 }
250 global;
251
252 static global Globals;
253
254 /* 
255  * This structure describes a single service. 
256  */
257 typedef struct
258 {
259         BOOL valid;
260         BOOL autoloaded;
261         char *szService;
262         char *szPath;
263         char *szUsername;
264         char **szInvalidUsers;
265         char **szValidUsers;
266         char **szAdminUsers;
267         char *szCopy;
268         char *szInclude;
269         char *szPrintcommand;
270         char *szLpqcommand;
271         char *szLprmcommand;
272         char *szLppausecommand;
273         char *szLpresumecommand;
274         char *szQueuepausecommand;
275         char *szQueueresumecommand;
276         char *szPrintername;
277         char **szHostsallow;
278         char **szHostsdeny;
279         char *comment;
280         char *volume;
281         char *fstype;
282         char *szMSDfsProxy;
283         char **ntvfs_handler;
284         int iMinPrintSpace;
285         int iMaxPrintJobs;
286         int iMaxConnections;
287         int iPrinting;
288         int iCSCPolicy;
289         BOOL bAvailable;
290         BOOL bBrowseable;
291         BOOL bRead_only;
292         BOOL bPrint_ok;
293         BOOL bMap_system;
294         BOOL bMap_hidden;
295         BOOL bMap_archive;
296         BOOL bLocking;
297         BOOL bStrictLocking;
298         BOOL bPosixLocking;
299         BOOL bOpLocks;
300         BOOL bLevel2OpLocks;
301         BOOL bOnlyUser;
302         BOOL bGuest_only;
303         BOOL bGuest_ok;
304         BOOL *copymap;
305         BOOL bMSDfsRoot;
306         BOOL bShareModes;
307         BOOL bStrictSync;
308         BOOL bCIFileSystem;
309         struct param_opt *param_opt;
310
311         char dummy[3];          /* for alignment */
312 }
313 service;
314
315
316 /* This is a default service used to prime a services structure */
317 static service sDefault = {
318         True,                   /* valid */
319         False,                  /* not autoloaded */
320         NULL,                   /* szService */
321         NULL,                   /* szPath */
322         NULL,                   /* szUsername */
323         NULL,                   /* szInvalidUsers */
324         NULL,                   /* szValidUsers */
325         NULL,                   /* szAdminUsers */
326         NULL,                   /* szCopy */
327         NULL,                   /* szInclude */
328         NULL,                   /* szPrintcommand */
329         NULL,                   /* szLpqcommand */
330         NULL,                   /* szLprmcommand */
331         NULL,                   /* szLppausecommand */
332         NULL,                   /* szLpresumecommand */
333         NULL,                   /* szQueuepausecommand */
334         NULL,                   /* szQueueresumecommand */
335         NULL,                   /* szPrintername */
336         NULL,                   /* szHostsallow */
337         NULL,                   /* szHostsdeny */
338         NULL,                   /* comment */
339         NULL,                   /* volume */
340         NULL,                   /* fstype */
341         NULL,                   /* szMSDfsProxy */
342         NULL,                   /* ntvfs_handler */
343         0,                      /* iMinPrintSpace */
344         1000,                   /* iMaxPrintJobs */
345         0,                      /* iMaxConnections */
346         DEFAULT_PRINTING,       /* iPrinting */
347         0,                      /* iCSCPolicy */
348         True,                   /* bAvailable */
349         True,                   /* bBrowseable */
350         True,                   /* bRead_only */
351         False,                  /* bPrint_ok */
352         False,                  /* bMap_system */
353         False,                  /* bMap_hidden */
354         True,                   /* bMap_archive */
355         True,                   /* bLocking */
356         True,                   /* bStrictLocking */
357         True,                   /* bPosixLocking */
358         True,                   /* bOpLocks */
359         True,                   /* bLevel2OpLocks */
360         False,                  /* bOnlyUser */
361         False,                  /* bGuest_only */
362         False,                  /* bGuest_ok */
363         NULL,                   /* copymap */
364         False,                  /* bMSDfsRoot */
365         True,                   /* bShareModes */
366         False,                  /* bStrictSync */
367         False,                  /* bCIFileSystem */
368         NULL,                   /* Parametric options */
369
370         ""                      /* dummy */
371 };
372
373 /* local variables */
374 static service **ServicePtrs = NULL;
375 static int iNumServices = 0;
376 static int iServiceIndex = 0;
377 static BOOL bInGlobalSection = True;
378 static BOOL bGlobalOnly = False;
379 static int server_role;
380 static int default_server_announce;
381
382 #define NUMPARAMETERS (sizeof(parm_table) / sizeof(struct parm_struct))
383
384 /* prototypes for the special type handlers */
385 static BOOL handle_include(const char *pszParmValue, char **ptr);
386 static BOOL handle_copy(const char *pszParmValue, char **ptr);
387 static BOOL handle_winbind_uid(const char *pszParmValue, char **ptr);
388 static BOOL handle_winbind_gid(const char *pszParmValue, char **ptr);
389 static BOOL handle_non_unix_account_range(const char *pszParmValue, char **ptr);
390
391 static void set_server_role(void);
392 static void set_default_server_announce_type(void);
393
394 static const struct enum_list enum_protocol[] = {
395         {PROTOCOL_NT1, "NT1"},
396         {PROTOCOL_LANMAN2, "LANMAN2"},
397         {PROTOCOL_LANMAN1, "LANMAN1"},
398         {PROTOCOL_CORE, "CORE"},
399         {PROTOCOL_COREPLUS, "COREPLUS"},
400         {PROTOCOL_COREPLUS, "CORE+"},
401         {-1, NULL}
402 };
403
404 static const struct enum_list enum_security[] = {
405         {SEC_SHARE, "SHARE"},
406         {SEC_USER, "USER"},
407         {SEC_SERVER, "SERVER"},
408         {SEC_DOMAIN, "DOMAIN"},
409 #ifdef HAVE_ADS
410         {SEC_ADS, "ADS"},
411 #endif
412         {-1, NULL}
413 };
414
415 static const struct enum_list enum_printing[] = {
416         {PRINT_SYSV, "sysv"},
417         {PRINT_AIX, "aix"},
418         {PRINT_HPUX, "hpux"},
419         {PRINT_BSD, "bsd"},
420         {PRINT_QNX, "qnx"},
421         {PRINT_PLP, "plp"},
422         {PRINT_LPRNG, "lprng"},
423         {PRINT_SOFTQ, "softq"},
424         {PRINT_CUPS, "cups"},
425         {PRINT_LPRNT, "nt"},
426         {PRINT_LPROS2, "os2"},
427 #ifdef DEVELOPER
428         {PRINT_TEST, "test"},
429         {PRINT_VLP, "vlp"},
430 #endif /* DEVELOPER */
431         {-1, NULL}
432 };
433
434 /* Types of machine we can announce as. */
435 #define ANNOUNCE_AS_NT_SERVER 1
436 #define ANNOUNCE_AS_WIN95 2
437 #define ANNOUNCE_AS_WFW 3
438 #define ANNOUNCE_AS_NT_WORKSTATION 4
439
440 static const struct enum_list enum_announce_as[] = {
441         {ANNOUNCE_AS_NT_SERVER, "NT"},
442         {ANNOUNCE_AS_NT_SERVER, "NT Server"},
443         {ANNOUNCE_AS_NT_WORKSTATION, "NT Workstation"},
444         {ANNOUNCE_AS_WIN95, "win95"},
445         {ANNOUNCE_AS_WFW, "WfW"},
446         {-1, NULL}
447 };
448
449 static const struct enum_list enum_bool_auto[] = {
450         {False, "No"},
451         {False, "False"},
452         {False, "0"},
453         {True, "Yes"},
454         {True, "True"},
455         {True, "1"},
456         {Auto, "Auto"},
457         {-1, NULL}
458 };
459
460 /* Client-side offline caching policy types */
461 #define CSC_POLICY_MANUAL 0
462 #define CSC_POLICY_DOCUMENTS 1
463 #define CSC_POLICY_PROGRAMS 2
464 #define CSC_POLICY_DISABLE 3
465
466 static const struct enum_list enum_csc_policy[] = {
467         {CSC_POLICY_MANUAL, "manual"},
468         {CSC_POLICY_DOCUMENTS, "documents"},
469         {CSC_POLICY_PROGRAMS, "programs"},
470         {CSC_POLICY_DISABLE, "disable"},
471         {-1, NULL}
472 };
473
474 /* SMB signing types. */
475 static const struct enum_list enum_smb_signing_vals[] = {
476         {SMB_SIGNING_OFF, "No"},
477         {SMB_SIGNING_OFF, "False"},
478         {SMB_SIGNING_OFF, "0"},
479         {SMB_SIGNING_OFF, "Off"},
480         {SMB_SIGNING_OFF, "disabled"},
481         {SMB_SIGNING_SUPPORTED, "Yes"},
482         {SMB_SIGNING_SUPPORTED, "True"},
483         {SMB_SIGNING_SUPPORTED, "1"},
484         {SMB_SIGNING_SUPPORTED, "On"},
485         {SMB_SIGNING_SUPPORTED, "enabled"},
486         {SMB_SIGNING_REQUIRED, "required"},
487         {SMB_SIGNING_REQUIRED, "mandatory"},
488         {SMB_SIGNING_REQUIRED, "force"},
489         {SMB_SIGNING_REQUIRED, "forced"},
490         {SMB_SIGNING_REQUIRED, "enforced"},
491         {SMB_SIGNING_AUTO, "auto"},
492         {-1, NULL}
493 };
494
495
496 /* Note: We do not initialise the defaults union - it is not allowed in ANSI C
497  *
498  * Note: We have a flag called FLAG_DEVELOPER but is not used at this time, it
499  * is implied in current control logic. This may change at some later time. A
500  * flag value of 0 means - show as development option only.
501  *
502  * The FLAG_HIDE is explicit. Paramters set this way do NOT appear in any edit
503  * screen in SWAT. This is used to exclude parameters as well as to squash all
504  * parameters that have been duplicated by pseudonyms.
505  */
506 static struct parm_struct parm_table[] = {
507         {"Base Options", P_SEP, P_SEPARATOR},
508
509         {"dos charset", P_STRING, P_GLOBAL, &Globals.dos_charset, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
510         {"unix charset", P_STRING, P_GLOBAL, &Globals.unix_charset, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
511         {"ncalrpc dir", P_STRING, P_GLOBAL, &Globals.ncalrpc_dir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
512         {"display charset", P_STRING, P_GLOBAL, &Globals.display_charset, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
513         {"comment", P_STRING, P_LOCAL, &sDefault.comment, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
514         {"path", P_STRING, P_LOCAL, &sDefault.szPath, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
515         {"directory", P_STRING, P_LOCAL, &sDefault.szPath, NULL, NULL, FLAG_HIDE},
516         {"workgroup", P_USTRING, P_GLOBAL, &Globals.szWorkgroup, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
517         {"realm", P_STRING, P_GLOBAL, &Globals.szRealm, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
518         {"ADS server", P_STRING, P_GLOBAL, &Globals.szADSserver, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
519         {"netbios name", P_USTRING, P_GLOBAL, &Globals.szNetbiosName, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
520         {"netbios aliases", P_LIST, P_GLOBAL, &Globals.szNetbiosAliases, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
521         {"netbios scope", P_USTRING, P_GLOBAL, &Globals.szNetbiosScope, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
522         {"server string", P_STRING, P_GLOBAL, &Globals.szServerString, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED  | FLAG_DEVELOPER},
523         {"interfaces", P_LIST, P_GLOBAL, &Globals.szInterfaces, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
524         {"bind interfaces only", P_BOOL, P_GLOBAL, &Globals.bBindInterfacesOnly, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
525         {"ntvfs handler", P_LIST, P_LOCAL, &sDefault.ntvfs_handler, NULL, NULL, FLAG_ADVANCED},
526         {"dcerpc endpoint servers", P_LIST, P_GLOBAL, &Globals.dcerpc_ep_servers, NULL, NULL, FLAG_ADVANCED},
527         {"server services", P_LIST, P_GLOBAL, &Globals.server_services, NULL, NULL, FLAG_ADVANCED},
528
529         {"Security Options", P_SEP, P_SEPARATOR},
530         
531         {"security", P_ENUM, P_GLOBAL, &Globals.security, NULL, enum_security, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
532         {"auth methods", P_LIST, P_GLOBAL, &Globals.AuthMethods, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
533         {"encrypt passwords", P_BOOL, P_GLOBAL, &Globals.bEncryptPasswords, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
534         {"allow trusted domains", P_BOOL, P_GLOBAL, &Globals.bAllowTrustedDomains, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
535         {"hosts equiv", P_STRING, P_GLOBAL, &Globals.szHostsEquiv, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
536         {"idmap backend", P_STRING, P_GLOBAL, &Globals.szIDMapBackend, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
537         {"null passwords", P_BOOL, P_GLOBAL, &Globals.bNullPasswords, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
538         {"obey pam restrictions", P_BOOL, P_GLOBAL, &Globals.bObeyPamRestrictions, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
539         {"password server", P_LIST, P_GLOBAL, &Globals.szPasswordServers, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
540         {"smb passwd file", P_STRING, P_GLOBAL, &Globals.szSMBPasswdFile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
541         {"sam database", P_STRING, P_GLOBAL, &Globals.szSAM_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
542         {"spoolss database", P_STRING, P_GLOBAL, &Globals.szSPOOLSS_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
543         {"wins database", P_STRING, P_GLOBAL, &Globals.szWINS_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
544         {"private dir", P_STRING, P_GLOBAL, &Globals.szPrivateDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
545         {"non unix account range", P_STRING, P_GLOBAL, &Globals.szNonUnixAccountRange, handle_non_unix_account_range, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
546         {"root directory", P_STRING, P_GLOBAL, &Globals.szRootdir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
547         {"root dir", P_STRING, P_GLOBAL, &Globals.szRootdir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
548         {"root", P_STRING, P_GLOBAL, &Globals.szRootdir, NULL, NULL, FLAG_HIDE | FLAG_DEVELOPER},
549         {"guest account", P_STRING, P_GLOBAL, &Globals.szGuestaccount, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
550         
551         {"pam password change", P_BOOL, P_GLOBAL, &Globals.bPamPasswordChange, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
552         {"passwd program", P_STRING, P_GLOBAL, &Globals.szPasswdProgram, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
553         {"passwd chat", P_STRING, P_GLOBAL, &Globals.szPasswdChat, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
554         {"password level", P_INTEGER, P_GLOBAL, &Globals.pwordlevel, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
555         {"username level", P_INTEGER, P_GLOBAL, &Globals.unamelevel, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
556         {"restrict anonymous", P_INTEGER, P_GLOBAL, &Globals.restrict_anonymous, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
557         {"lanman auth", P_BOOL, P_GLOBAL, &Globals.bLanmanAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
558         {"ntlm auth", P_BOOL, P_GLOBAL, &Globals.bNTLMAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
559         {"client NTLMv2 auth", P_BOOL, P_GLOBAL, &Globals.bClientNTLMv2Auth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
560         {"client lanman auth", P_BOOL, P_GLOBAL, &Globals.bClientLanManAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
561         
562         {"username", P_STRING, P_LOCAL, &sDefault.szUsername, NULL, NULL, FLAG_GLOBAL | FLAG_SHARE},
563         {"user", P_STRING, P_LOCAL, &sDefault.szUsername, NULL, NULL, FLAG_HIDE},
564         {"users", P_STRING, P_LOCAL, &sDefault.szUsername, NULL, NULL, FLAG_HIDE},
565         
566         {"invalid users", P_LIST, P_LOCAL, &sDefault.szInvalidUsers, NULL, NULL, FLAG_GLOBAL | FLAG_SHARE},
567         {"valid users", P_LIST, P_LOCAL, &sDefault.szValidUsers, NULL, NULL, FLAG_GLOBAL | FLAG_SHARE},
568         {"admin users", P_LIST, P_LOCAL, &sDefault.szAdminUsers, NULL, NULL, FLAG_GLOBAL | FLAG_SHARE},
569         
570         {"read only", P_BOOL, P_LOCAL, &sDefault.bRead_only, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE},
571
572         {"guest only", P_BOOL, P_LOCAL, &sDefault.bGuest_only, NULL, NULL, FLAG_SHARE},
573
574         {"guest ok", P_BOOL, P_LOCAL, &sDefault.bGuest_ok, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
575
576         {"only user", P_BOOL, P_LOCAL, &sDefault.bOnlyUser, NULL, NULL, FLAG_SHARE},
577         {"hosts allow", P_LIST, P_LOCAL, &sDefault.szHostsallow, NULL, NULL, FLAG_GLOBAL | FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
578         {"hosts deny", P_LIST, P_LOCAL, &sDefault.szHostsdeny, NULL, NULL, FLAG_GLOBAL | FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
579         {"preload modules", P_LIST, P_GLOBAL, &Globals.szPreloadModules, NULL, NULL, FLAG_BASIC | FLAG_GLOBAL},
580
581         {"Logging Options", P_SEP, P_SEPARATOR},
582
583         {"log level", P_INTEGER, P_GLOBAL, &DEBUGLEVEL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
584         {"debuglevel", P_INTEGER, P_GLOBAL, &DEBUGLEVEL, NULL, NULL, FLAG_HIDE},
585         {"log file", P_STRING, P_GLOBAL, &Globals.szLogFile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
586         
587         {"Protocol Options", P_SEP, P_SEPARATOR},
588         
589         {"smb ports", P_LIST, P_GLOBAL, &Globals.smb_ports, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
590         {"nbt port", P_INTEGER, P_GLOBAL, &Globals.nbt_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
591         {"dgram port", P_INTEGER, P_GLOBAL, &Globals.dgram_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
592         {"cldap port", P_INTEGER, P_GLOBAL, &Globals.cldap_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
593         {"web port", P_INTEGER, P_GLOBAL, &Globals.web_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
594         {"swat directory", P_STRING, P_GLOBAL, &Globals.swat_directory, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
595         {"large readwrite", P_BOOL, P_GLOBAL, &Globals.bLargeReadwrite, NULL, NULL, FLAG_DEVELOPER},
596         {"max protocol", P_ENUM, P_GLOBAL, &Globals.maxprotocol, NULL, enum_protocol, FLAG_DEVELOPER},
597         {"min protocol", P_ENUM, P_GLOBAL, &Globals.minprotocol, NULL, enum_protocol, FLAG_DEVELOPER},
598         {"unicode", P_BOOL, P_GLOBAL, &Globals.bUnicode, NULL, NULL, FLAG_DEVELOPER},
599         {"read raw", P_BOOL, P_GLOBAL, &Globals.bReadRaw, NULL, NULL, FLAG_DEVELOPER},
600         {"write raw", P_BOOL, P_GLOBAL, &Globals.bWriteRaw, NULL, NULL, FLAG_DEVELOPER},
601         {"disable netbios", P_BOOL, P_GLOBAL, &Globals.bDisableNetbios, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
602         
603         {"nt status support", P_BOOL, P_GLOBAL, &Globals.bNTStatusSupport, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
604
605         {"announce version", P_STRING, P_GLOBAL, &Globals.szAnnounceVersion, NULL, NULL, FLAG_DEVELOPER},
606         {"announce as", P_ENUM, P_GLOBAL, &Globals.announce_as, NULL, enum_announce_as, FLAG_DEVELOPER},
607         {"max mux", P_INTEGER, P_GLOBAL, &Globals.max_mux, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
608         {"max xmit", P_INTEGER, P_GLOBAL, &Globals.max_xmit, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
609
610         {"name resolve order", P_LIST, P_GLOBAL, &Globals.szNameResolveOrder, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
611         {"max ttl", P_INTEGER, P_GLOBAL, &Globals.max_ttl, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER}, 
612         {"max wins ttl", P_INTEGER, P_GLOBAL, &Globals.max_wins_ttl, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
613         {"min wins ttl", P_INTEGER, P_GLOBAL, &Globals.min_wins_ttl, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
614         {"time server", P_BOOL, P_GLOBAL, &Globals.bTimeServer, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
615         {"unix extensions", P_BOOL, P_GLOBAL, &Globals.bUnixExtensions, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
616         {"use spnego", P_BOOL, P_GLOBAL, &Globals.bUseSpnego, NULL, NULL, FLAG_DEVELOPER},
617         {"server signing", P_ENUM, P_GLOBAL, &Globals.server_signing, NULL, enum_smb_signing_vals, FLAG_ADVANCED}, 
618         {"client signing", P_ENUM, P_GLOBAL, &Globals.client_signing, NULL, enum_smb_signing_vals, FLAG_ADVANCED}, 
619         {"rpc big endian", P_BOOL, P_GLOBAL, &Globals.bRpcBigEndian, NULL, NULL, FLAG_DEVELOPER},
620
621         {"Tuning Options", P_SEP, P_SEPARATOR},
622                 
623         {"lpq cache time", P_INTEGER, P_GLOBAL, &Globals.lpqcachetime, NULL, NULL, FLAG_DEVELOPER},
624         {"max connections", P_INTEGER, P_LOCAL, &sDefault.iMaxConnections, NULL, NULL, FLAG_SHARE},
625         {"paranoid server security", P_BOOL, P_GLOBAL, &Globals.paranoid_server_security, NULL, NULL, FLAG_DEVELOPER},
626         {"min print space", P_INTEGER, P_LOCAL, &sDefault.iMinPrintSpace, NULL, NULL, FLAG_PRINT},
627         
628         {"socket options", P_STRING, P_GLOBAL, &Globals.socket_options, NULL, NULL, FLAG_DEVELOPER},
629         {"use mmap", P_BOOL, P_GLOBAL, &Globals.bUseMmap, NULL, NULL, FLAG_DEVELOPER},
630         {"hostname lookups", P_BOOL, P_GLOBAL, &Globals.bHostnameLookups, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
631
632         {"name cache timeout", P_INTEGER, P_GLOBAL, &Globals.name_cache_timeout, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
633         {"strict sync", P_BOOL, P_LOCAL, &sDefault.bStrictSync, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
634         {"case insensitive filesystem", P_BOOL, P_LOCAL, &sDefault.bCIFileSystem, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
635
636         {"Printing Options", P_SEP, P_SEPARATOR},
637         
638         {"max print jobs", P_INTEGER, P_LOCAL, &sDefault.iMaxPrintJobs, NULL, NULL, FLAG_PRINT},
639         {"load printers", P_BOOL, P_GLOBAL, &Globals.bLoadPrinters, NULL, NULL, FLAG_PRINT},
640         {"printcap name", P_STRING, P_GLOBAL, &Globals.szPrintcapname, NULL, NULL, FLAG_PRINT | FLAG_DEVELOPER},
641         {"printcap", P_STRING, P_GLOBAL, &Globals.szPrintcapname, NULL, NULL, FLAG_HIDE},
642         {"printable", P_BOOL, P_LOCAL, &sDefault.bPrint_ok, NULL, NULL, FLAG_PRINT},
643         {"print ok", P_BOOL, P_LOCAL, &sDefault.bPrint_ok, NULL, NULL, FLAG_HIDE},
644         {"printing", P_ENUM, P_LOCAL, &sDefault.iPrinting, NULL, enum_printing, FLAG_PRINT | FLAG_GLOBAL},
645         {"print command", P_STRING, P_LOCAL, &sDefault.szPrintcommand, NULL, NULL, FLAG_PRINT | FLAG_GLOBAL},
646         {"disable spoolss", P_BOOL, P_GLOBAL, &Globals.bDisableSpoolss, NULL, NULL, FLAG_PRINT | FLAG_GLOBAL},
647         {"lpq command", P_STRING, P_LOCAL, &sDefault.szLpqcommand, NULL, NULL, FLAG_PRINT | FLAG_GLOBAL},
648         {"lprm command", P_STRING, P_LOCAL, &sDefault.szLprmcommand, NULL, NULL, FLAG_PRINT | FLAG_GLOBAL},
649         {"lppause command", P_STRING, P_LOCAL, &sDefault.szLppausecommand, NULL, NULL, FLAG_PRINT | FLAG_GLOBAL},
650         {"lpresume command", P_STRING, P_LOCAL, &sDefault.szLpresumecommand, NULL, NULL, FLAG_PRINT | FLAG_GLOBAL},
651         {"queuepause command", P_STRING, P_LOCAL, &sDefault.szQueuepausecommand, NULL, NULL, FLAG_PRINT | FLAG_GLOBAL},
652         {"queueresume command", P_STRING, P_LOCAL, &sDefault.szQueueresumecommand, NULL, NULL, FLAG_PRINT | FLAG_GLOBAL},
653         
654         {"printer name", P_STRING, P_LOCAL, &sDefault.szPrintername, NULL, NULL, FLAG_PRINT},
655         {"printer", P_STRING, P_LOCAL, &sDefault.szPrintername, NULL, NULL, FLAG_HIDE},
656
657         {"Filename Handling", P_SEP, P_SEPARATOR},
658         
659         {"map system", P_BOOL, P_LOCAL, &sDefault.bMap_system, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
660         {"map hidden", P_BOOL, P_LOCAL, &sDefault.bMap_hidden, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
661         {"map archive", P_BOOL, P_LOCAL, &sDefault.bMap_archive, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
662
663         {"Domain Options", P_SEP, P_SEPARATOR},
664         
665         {"machine password timeout", P_INTEGER, P_GLOBAL, &Globals.machine_password_timeout, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
666
667         {"Logon Options", P_SEP, P_SEPARATOR},
668
669         {"add user script", P_STRING, P_GLOBAL, &Globals.szAddUserScript, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
670         {"add machine script", P_STRING, P_GLOBAL, &Globals.szAddMachineScript, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
671
672         {"logon script", P_STRING, P_GLOBAL, &Globals.szLogonScript, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
673         {"logon path", P_STRING, P_GLOBAL, &Globals.szLogonPath, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
674         {"logon drive", P_STRING, P_GLOBAL, &Globals.szLogonDrive, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
675         {"logon home", P_STRING, P_GLOBAL, &Globals.szLogonHome, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
676         {"domain logons", P_BOOL, P_GLOBAL, &Globals.bDomainLogons, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
677
678         {"Browse Options", P_SEP, P_SEPARATOR},
679         
680         {"os level", P_INTEGER, P_GLOBAL, &Globals.os_level, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
681         {"lm announce", P_ENUM, P_GLOBAL, &Globals.lm_announce, NULL, enum_bool_auto, FLAG_ADVANCED | FLAG_DEVELOPER},
682         {"lm interval", P_INTEGER, P_GLOBAL, &Globals.lm_interval, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
683         {"preferred master", P_ENUM, P_GLOBAL, &Globals.bPreferredMaster, NULL, enum_bool_auto, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
684         {"prefered master", P_ENUM, P_GLOBAL, &Globals.bPreferredMaster, NULL, enum_bool_auto, FLAG_HIDE},
685         {"local master", P_BOOL, P_GLOBAL, &Globals.bLocalMaster, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
686         {"domain master", P_ENUM, P_GLOBAL, &Globals.bDomainMaster, NULL, enum_bool_auto, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
687         {"browseable", P_BOOL, P_LOCAL, &sDefault.bBrowseable, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
688         {"browsable", P_BOOL, P_LOCAL, &sDefault.bBrowseable, NULL, NULL, FLAG_HIDE},
689         {"enhanced browsing", P_BOOL, P_GLOBAL, &Globals.enhanced_browsing, NULL, NULL, FLAG_DEVELOPER | FLAG_ADVANCED},
690
691         {"WINS Options", P_SEP, P_SEPARATOR},
692         {"dns proxy", P_BOOL, P_GLOBAL, &Globals.bDNSproxy, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
693         {"wins proxy", P_BOOL, P_GLOBAL, &Globals.bWINSproxy, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
694         
695         {"wins server", P_LIST, P_GLOBAL, &Globals.szWINSservers, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
696         {"wins support", P_BOOL, P_GLOBAL, &Globals.bWINSsupport, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
697         {"wins hook", P_STRING, P_GLOBAL, &Globals.szWINSHook, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
698         {"wins partners", P_STRING, P_GLOBAL, &Globals.szWINSPartners, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
699
700         {"Locking Options", P_SEP, P_SEPARATOR},
701         
702         {"csc policy", P_ENUM, P_LOCAL, &sDefault.iCSCPolicy, NULL, enum_csc_policy, FLAG_SHARE | FLAG_GLOBAL},
703         {"locking", P_BOOL, P_LOCAL, &sDefault.bLocking, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
704         {"lock spin count", P_INTEGER, P_GLOBAL, &Globals.iLockSpinCount, NULL, NULL, FLAG_GLOBAL},
705         {"lock spin time", P_INTEGER, P_GLOBAL, &Globals.iLockSpinTime, NULL, NULL, FLAG_GLOBAL},
706         
707         {"oplocks", P_BOOL, P_LOCAL, &sDefault.bOpLocks, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
708         {"level2 oplocks", P_BOOL, P_LOCAL, &sDefault.bLevel2OpLocks, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
709         {"posix locking", P_BOOL, P_LOCAL, &sDefault.bPosixLocking, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
710         {"strict locking", P_BOOL, P_LOCAL, &sDefault.bStrictLocking, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
711         {"share modes", P_BOOL, P_LOCAL,  &sDefault.bShareModes, NULL, NULL, FLAG_SHARE|FLAG_GLOBAL},
712
713         {"Miscellaneous Options", P_SEP, P_SEPARATOR},
714         
715         {"config file", P_STRING, P_GLOBAL, &Globals.szConfigFile, NULL, NULL, FLAG_HIDE},
716         {"preload", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
717         {"auto services", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
718         {"lock dir", P_STRING, P_GLOBAL, &Globals.szLockDir, NULL, NULL, FLAG_HIDE}, 
719         {"lock directory", P_STRING, P_GLOBAL, &Globals.szLockDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
720         {"pid directory", P_STRING, P_GLOBAL, &Globals.szPidDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER}, 
721         
722         {"default service", P_STRING, P_GLOBAL, &Globals.szDefaultService, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
723         {"default", P_STRING, P_GLOBAL, &Globals.szDefaultService, NULL, NULL,  FLAG_DEVELOPER},
724         {"remote announce", P_STRING, P_GLOBAL, &Globals.szRemoteAnnounce, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
725         {"remote browse sync", P_STRING, P_GLOBAL, &Globals.szRemoteBrowseSync, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
726         {"socket address", P_STRING, P_GLOBAL, &Globals.szSocketAddress, NULL, NULL, FLAG_DEVELOPER},
727         {"time offset", P_INTEGER, P_GLOBAL, &Globals.time_offset, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
728         {"-valid", P_BOOL, P_LOCAL, &sDefault.valid, NULL, NULL, FLAG_HIDE},
729         
730         {"copy", P_STRING, P_LOCAL, &sDefault.szCopy, handle_copy, NULL, FLAG_HIDE},
731         {"include", P_STRING, P_LOCAL, &sDefault.szInclude, handle_include, NULL, FLAG_HIDE},
732         
733         {"available", P_BOOL, P_LOCAL, &sDefault.bAvailable, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT},
734         {"volume", P_STRING, P_LOCAL, &sDefault.volume, NULL, NULL, FLAG_SHARE },
735         {"fstype", P_STRING, P_LOCAL, &sDefault.fstype, NULL, NULL, FLAG_SHARE},
736
737         {"panic action", P_STRING, P_GLOBAL, &Globals.szPanicAction, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
738         {"hide local users", P_BOOL, P_GLOBAL, &Globals.bHideLocalUsers, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
739
740         {"msdfs root", P_BOOL, P_LOCAL, &sDefault.bMSDfsRoot, NULL, NULL, FLAG_SHARE},
741         {"msdfs proxy", P_STRING, P_LOCAL, &sDefault.szMSDfsProxy, NULL, NULL, FLAG_SHARE},
742         {"host msdfs", P_BOOL, P_GLOBAL, &Globals.bHostMSDfs, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
743         {"Winbind options", P_SEP, P_SEPARATOR},
744
745         {"winbind uid", P_STRING, P_GLOBAL, &Globals.szWinbindUID, handle_winbind_uid, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
746         {"winbind gid", P_STRING, P_GLOBAL, &Globals.szWinbindGID, handle_winbind_gid, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
747         {"template homedir", P_STRING, P_GLOBAL, &Globals.szTemplateHomedir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
748         {"template shell", P_STRING, P_GLOBAL, &Globals.szTemplateShell, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
749         {"winbind separator", P_STRING, P_GLOBAL, &Globals.szWinbindSeparator, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
750         {"winbind cache time", P_INTEGER, P_GLOBAL, &Globals.winbind_cache_time, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
751         {"winbind enum users", P_BOOL, P_GLOBAL, &Globals.bWinbindEnumUsers, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
752         {"winbind enum groups", P_BOOL, P_GLOBAL, &Globals.bWinbindEnumGroups, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
753         {"winbind use default domain", P_BOOL, P_GLOBAL, &Globals.bWinbindUseDefaultDomain, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
754
755         {NULL, P_BOOL, P_NONE, NULL, NULL, NULL, 0}
756 };
757
758 /***************************************************************************
759  Initialise the sDefault parameter structure for the printer values.
760 ***************************************************************************/
761
762 static void init_printer_values(void)
763 {
764         /* choose defaults depending on the type of printing */
765         switch (sDefault.iPrinting) {
766                 case PRINT_BSD:
767                 case PRINT_AIX:
768                 case PRINT_LPRNT:
769                 case PRINT_LPROS2:
770                         do_parameter("Lpqcommand", "lpq -P'%p'");
771                         do_parameter("Lprmcommand", "lprm -P'%p' %j");
772                         do_parameter("Printcommand",
773                                    "lpr -r -P'%p' %s");
774                         break;
775
776                 case PRINT_LPRNG:
777                 case PRINT_PLP:
778                         do_parameter("Lpqcommand", "lpq -P'%p'");
779                         do_parameter("Lprmcommand", "lprm -P'%p' %j");
780                         do_parameter("Printcommand",
781                                    "lpr -r -P'%p' %s");
782                         do_parameter("Queuepausecommand",
783                                    "lpc stop '%p'");
784                         do_parameter("Queueresumecommand",
785                                    "lpc start '%p'");
786                         do_parameter("Lppausecommand",
787                                    "lpc hold '%p' %j");
788                         do_parameter("Lpresumecommand",
789                                    "lpc release '%p' %j");
790                         break;
791
792                 case PRINT_CUPS:
793 #ifdef HAVE_CUPS
794                         do_parameter("Lpqcommand", "");
795                         do_parameter("Lprmcommand", "");
796                         do_parameter("Printcommand", "");
797                         do_parameter("Lppausecommand", "");
798                         do_parameter("Lpresumecommand", "");
799                         do_parameter("Queuepausecommand", "");
800                         do_parameter("Queueresumecommand", "");
801
802                         do_parameter("Printcapname", "cups");
803 #else
804                         do_parameter("Lpqcommand",
805                                    "/usr/bin/lpstat -o '%p'");
806                         do_parameter("Lprmcommand",
807                                    "/usr/bin/cancel '%p-%j'");
808                         do_parameter("Printcommand",
809                                    "/usr/bin/lp -d '%p' %s; rm %s");
810                         do_parameter("Lppausecommand",
811                                    "lp -i '%p-%j' -H hold");
812                         do_parameter("Lpresumecommand",
813                                    "lp -i '%p-%j' -H resume");
814                         do_parameter("Queuepausecommand",
815                                    "/usr/bin/disable '%p'");
816                         do_parameter("Queueresumecommand",
817                                    "/usr/bin/enable '%p'");
818                         do_parameter("Printcapname", "lpstat");
819 #endif /* HAVE_CUPS */
820                         break;
821
822                 case PRINT_SYSV:
823                 case PRINT_HPUX:
824                         do_parameter("Lpqcommand", "lpstat -o%p");
825                         do_parameter("Lprmcommand", "cancel %p-%j");
826                         do_parameter("Printcommand",
827                                    "lp -c -d%p %s; rm %s");
828                         do_parameter("Queuepausecommand",
829                                    "disable %p");
830                         do_parameter("Queueresumecommand",
831                                    "enable %p");
832 #ifndef HPUX
833                         do_parameter("Lppausecommand",
834                                    "lp -i %p-%j -H hold");
835                         do_parameter("Lpresumecommand",
836                                    "lp -i %p-%j -H resume");
837 #endif /* HPUX */
838                         break;
839
840                 case PRINT_QNX:
841                         do_parameter("Lpqcommand", "lpq -P%p");
842                         do_parameter("Lprmcommand", "lprm -P%p %j");
843                         do_parameter("Printcommand", "lp -r -P%p %s");
844                         break;
845
846                 case PRINT_SOFTQ:
847                         do_parameter("Lpqcommand", "qstat -l -d%p");
848                         do_parameter("Lprmcommand",
849                                    "qstat -s -j%j -c");
850                         do_parameter("Printcommand",
851                                    "lp -d%p -s %s; rm %s");
852                         do_parameter("Lppausecommand",
853                                    "qstat -s -j%j -h");
854                         do_parameter("Lpresumecommand",
855                                    "qstat -s -j%j -r");
856                         break;
857 #ifdef DEVELOPER
858         case PRINT_TEST:
859         case PRINT_VLP:
860                 do_parameter("Printcommand", "vlp print %p %s");
861                 do_parameter("Lpqcommand", "vlp lpq %p");
862                 do_parameter("Lprmcommand", "vlp lprm %p %j");
863                 do_parameter("Lppausecommand", "vlp lppause %p %j");
864                 do_parameter("Lpresumecommand", "vlp lpresum %p %j");
865                 do_parameter("Queuepausecommand", "vlp queuepause %p");
866                 do_parameter("Queueresumecommand", "vlp queueresume %p");
867                 break;
868 #endif /* DEVELOPER */
869
870         }
871 }
872
873
874 /***************************************************************************
875  Initialise the global parameter structure.
876 ***************************************************************************/
877 static void init_globals(void)
878 {
879         int i;
880         char *myname;
881
882         DEBUG(3, ("Initialising global parameters\n"));
883
884         for (i = 0; parm_table[i].label; i++) {
885                 if ((parm_table[i].type == P_STRING ||
886                      parm_table[i].type == P_USTRING) &&
887                     parm_table[i].ptr &&
888                     !(parm_table[i].flags & FLAG_CMDLINE)) {
889                         string_set(parm_table[i].ptr, "");
890                 }
891         }
892
893         /* options that can be set on the command line must be initialised via
894            the slower do_parameter() to ensure that FLAG_CMDLINE is obeyed */
895 #ifdef TCP_NODELAY
896         do_parameter("socket options", "TCP_NODELAY");
897 #endif
898         do_parameter("workgroup", DEFAULT_WORKGROUP);
899         myname = get_myname();
900         do_parameter("netbios name", myname);
901         SAFE_FREE(myname);
902         do_parameter("max protocol", "NT1");
903         do_parameter("name resolve order", "lmhosts wins host bcast");
904
905         init_printer_values();
906
907         do_parameter("fstype", FSTYPE_STRING);
908         do_parameter("ntvfs handler", "unixuid default");
909         do_parameter("max connections", "-1");
910
911         do_parameter("dcerpc endpoint servers", "epmapper srvsvc wkssvc rpcecho samr netlogon lsarpc spoolss drsuapi winreg dssetup");
912         do_parameter("server services", "smb rpc nbt ldap cldap web");
913         do_parameter("auth methods", "anonymous sam_ignoredomain");
914         do_parameter("smb passwd file", dyn_SMB_PASSWD_FILE);
915         do_parameter("private dir", dyn_PRIVATE_DIR);
916         do_parameter_var("sam database", "tdb://%s/sam.ldb", dyn_PRIVATE_DIR);
917         do_parameter_var("spoolss database", "tdb://%s/spoolss.ldb", dyn_PRIVATE_DIR);
918         do_parameter_var("wins database", "tdb://%s/wins.ldb", dyn_PRIVATE_DIR);
919         do_parameter_var("registry:HKEY_LOCAL_MACHINE", "ldb:/%s/hklm.ldb", dyn_PRIVATE_DIR);
920         do_parameter("guest account", GUEST_ACCOUNT);
921
922         /* using UTF8 by default allows us to support all chars */
923         do_parameter("unix charset", "UTF8");
924
925         /* Use codepage 850 as a default for the dos character set */
926         do_parameter("dos charset", "CP850");
927
928         /*
929          * Allow the default PASSWD_CHAT to be overridden in local.h.
930          */
931         do_parameter("passwd chat", DEFAULT_PASSWD_CHAT);
932
933         do_parameter("passwd program", "");
934         do_parameter("printcap name", PRINTCAP_NAME);
935         
936         do_parameter("pid directory", dyn_PIDDIR);
937         do_parameter("lock dir", dyn_LOCKDIR);
938         do_parameter("ncalrpc dir", dyn_NCALRPCDIR);
939
940         do_parameter("socket address", "0.0.0.0");
941         do_parameter_var("server string", "Samba %s", SAMBA_VERSION_STRING);
942
943         do_parameter_var("announce version", "%d.%d", 
944                          DEFAULT_MAJOR_VERSION,
945                          DEFAULT_MINOR_VERSION);
946
947         do_parameter("logon drive", "");
948
949         do_parameter("logon home", "\\\\%N\\%U");
950         do_parameter("logon path", "\\\\%N\\%U\\profile");
951         do_parameter("password server", "*");
952
953         do_parameter("load printers", "True");
954
955         do_parameter("max mux", "50");
956         do_parameter("max xmit", "12288");
957         do_parameter("lpqcachetime", "10");
958         do_parameter("DisableSpoolss", "False");
959         do_parameter("password level", "0");
960         do_parameter("username level", "0");
961         do_parameter("LargeReadwrite", "True");
962         do_parameter("minprotocol", "CORE");
963         do_parameter("security", "USER");
964         do_parameter("paranoid server security", "True");
965         do_parameter("EncryptPasswords", "True");
966         do_parameter("ReadRaw", "True");
967         do_parameter("WriteRaw", "True");
968         do_parameter("NullPasswords", "False");
969         do_parameter("ObeyPamRestrictions", "False");
970         do_parameter("lm announce", "Auto");    
971         do_parameter("lm interval", "60");
972         do_parameter("announce as", "NT SERVER");
973
974         do_parameter("TimeServer", "False");
975         do_parameter("BindInterfacesOnly", "False");
976         do_parameter("PamPasswordChange", "False");
977         do_parameter("Unicode", "True");
978         do_parameter("restrict anonymous", "0");
979         do_parameter("ClientLanManAuth", "True");
980         do_parameter("LanmanAuth", "True");
981         do_parameter("NTLMAuth", "True");
982         
983         do_parameter("enhanced browsing", "True"); 
984         do_parameter("LockSpinCount", "3");
985         do_parameter("LockSpinTime", "10");
986 #ifdef MMAP_BLACKLIST
987         do_parameter("UseMmap", "False");
988 #else
989         do_parameter("UseMmap", "True");
990 #endif
991         do_parameter("UnixExtensions", "False");
992
993         /* hostname lookups can be very expensive and are broken on
994            a large number of sites (tridge) */
995         do_parameter("HostnameLookups", "False");
996
997         do_parameter("PreferredMaster", "Auto");
998         do_parameter("os level", "20");
999         do_parameter("LocalMaster", "True");
1000         do_parameter("DomainMaster", "Auto");   /* depending on bDomainLogons */
1001         do_parameter("DomainLogons", "False");
1002         do_parameter("WINSsupport", "False");
1003         do_parameter("WINSproxy", "False");
1004
1005         do_parameter("DNSproxy", "True");
1006
1007         do_parameter("AllowTrustedDomains", "True");
1008
1009         do_parameter("TemplateShell", "/bin/false");
1010         do_parameter("TemplateHomedir", "/home/%D/%U");
1011         do_parameter("WinbindSeparator", "\\");
1012
1013         do_parameter("winbind cache time", "15");
1014         do_parameter("WinbindEnumUsers", "True");
1015         do_parameter("WinbindEnumGroups", "True");
1016         do_parameter("WinbindUseDefaultDomain", "False");
1017
1018         do_parameter("IDMapBackend", "tdb");
1019
1020         do_parameter("name cache timeout", "660"); /* In seconds */
1021
1022         do_parameter("client signing", "Yes");
1023         do_parameter("server signing", "auto");
1024
1025         do_parameter("use spnego", "True");
1026
1027         do_parameter("smb ports", SMB_PORTS);
1028         do_parameter("nbt port", "137");
1029         do_parameter("dgram port", "138");
1030         do_parameter("cldap port", "389");
1031         do_parameter("web port", "901");
1032         do_parameter("swat directory", dyn_SWATDIR);
1033
1034         do_parameter("nt status support", "True");
1035
1036         do_parameter("max wins ttl", "432000");
1037         do_parameter("min wins ttl", "10");
1038 }
1039
1040 static TALLOC_CTX *lp_talloc;
1041
1042 /******************************************************************* a
1043  Free up temporary memory - called from the main loop.
1044 ********************************************************************/
1045
1046 void lp_talloc_free(void)
1047 {
1048         if (!lp_talloc)
1049                 return;
1050         talloc_free(lp_talloc);
1051         lp_talloc = NULL;
1052 }
1053
1054 /*******************************************************************
1055  Convenience routine to grab string parameters into temporary memory
1056  and run standard_sub_basic on them. The buffers can be written to by
1057  callers without affecting the source string.
1058 ********************************************************************/
1059
1060 static const char *lp_string(const char *s)
1061 {
1062 #if 0  /* until REWRITE done to make thread-safe */
1063         size_t len = s ? strlen(s) : 0;
1064         char *ret;
1065 #endif
1066
1067         /* The follow debug is useful for tracking down memory problems
1068            especially if you have an inner loop that is calling a lp_*()
1069            function that returns a string.  Perhaps this debug should be
1070            present all the time? */
1071
1072 #if 0
1073         DEBUG(10, ("lp_string(%s)\n", s));
1074 #endif
1075
1076 #if 0  /* until REWRITE done to make thread-safe */
1077         if (!lp_talloc)
1078                 lp_talloc = talloc_init("lp_talloc");
1079
1080         ret = talloc_array(lp_talloc, char, len + 100); /* leave room for substitution */
1081
1082         if (!ret)
1083                 return NULL;
1084
1085         if (!s)
1086                 *ret = 0;
1087         else
1088                 StrnCpy(ret, s, len);
1089
1090         if (trim_string(ret, "\"", "\"")) {
1091                 if (strchr(ret,'"') != NULL)
1092                         StrnCpy(ret, s, len);
1093         }
1094
1095         standard_sub_basic(ret,len+100);
1096         return (ret);
1097 #endif
1098         return s;
1099 }
1100
1101 /*
1102    In this section all the functions that are used to access the 
1103    parameters from the rest of the program are defined 
1104 */
1105
1106 #define FN_GLOBAL_STRING(fn_name,ptr) \
1107  const char *fn_name(void) {return(lp_string(*(char **)(ptr) ? *(char **)(ptr) : ""));}
1108 #define FN_GLOBAL_CONST_STRING(fn_name,ptr) \
1109  const char *fn_name(void) {return(*(const char **)(ptr) ? *(const char **)(ptr) : "");}
1110 #define FN_GLOBAL_LIST(fn_name,ptr) \
1111  const char **fn_name(void) {return(*(const char ***)(ptr));}
1112 #define FN_GLOBAL_BOOL(fn_name,ptr) \
1113  BOOL fn_name(void) {return(*(BOOL *)(ptr));}
1114 #define FN_GLOBAL_CHAR(fn_name,ptr) \
1115  char fn_name(void) {return(*(char *)(ptr));}
1116 #define FN_GLOBAL_INTEGER(fn_name,ptr) \
1117  int fn_name(void) {return(*(int *)(ptr));}
1118
1119 #define FN_LOCAL_STRING(fn_name,val) \
1120  const char *fn_name(int i) {return(lp_string((LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val));}
1121 #define FN_LOCAL_CONST_STRING(fn_name,val) \
1122  const char *fn_name(int i) {return (const char *)((LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val);}
1123 #define FN_LOCAL_LIST(fn_name,val) \
1124  const char **fn_name(int i) {return(const char **)(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1125 #define FN_LOCAL_BOOL(fn_name,val) \
1126  BOOL fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1127 #define FN_LOCAL_CHAR(fn_name,val) \
1128  char fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1129 #define FN_LOCAL_INTEGER(fn_name,val) \
1130  int fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1131
1132 FN_GLOBAL_LIST(lp_smb_ports, &Globals.smb_ports)
1133 FN_GLOBAL_INTEGER(lp_nbt_port, &Globals.nbt_port)
1134 FN_GLOBAL_INTEGER(lp_dgram_port, &Globals.dgram_port)
1135 FN_GLOBAL_INTEGER(lp_cldap_port, &Globals.cldap_port)
1136 FN_GLOBAL_INTEGER(lp_web_port, &Globals.web_port)
1137 FN_GLOBAL_STRING(lp_dos_charset, &Globals.dos_charset)
1138 FN_GLOBAL_STRING(lp_swat_directory, &Globals.swat_directory)
1139 FN_GLOBAL_STRING(lp_unix_charset, &Globals.unix_charset)
1140 FN_GLOBAL_STRING(lp_display_charset, &Globals.display_charset)
1141 FN_GLOBAL_STRING(lp_logfile, &Globals.szLogFile)
1142 FN_GLOBAL_STRING(lp_configfile, &Globals.szConfigFile)
1143 FN_GLOBAL_STRING(lp_smb_passwd_file, &Globals.szSMBPasswdFile)
1144 FN_GLOBAL_STRING(lp_sam_url, &Globals.szSAM_URL)
1145 FN_GLOBAL_STRING(lp_spoolss_url, &Globals.szSPOOLSS_URL)
1146 FN_GLOBAL_STRING(lp_wins_url, &Globals.szWINS_URL)
1147 FN_GLOBAL_STRING(lp_private_dir, &Globals.szPrivateDir)
1148 FN_GLOBAL_STRING(lp_serverstring, &Globals.szServerString)
1149 FN_GLOBAL_STRING(lp_printcapname, &Globals.szPrintcapname)
1150 FN_GLOBAL_STRING(lp_lockdir, &Globals.szLockDir)
1151 FN_GLOBAL_STRING(lp_ncalrpc_dir, &Globals.ncalrpc_dir)
1152 FN_GLOBAL_STRING(lp_piddir, &Globals.szPidDir)
1153 FN_GLOBAL_LIST(lp_dcerpc_endpoint_servers, &Globals.dcerpc_ep_servers)
1154 FN_GLOBAL_LIST(lp_server_services, &Globals.server_services)
1155 FN_GLOBAL_STRING(lp_rootdir, &Globals.szRootdir)
1156 FN_GLOBAL_STRING(lp_defaultservice, &Globals.szDefaultService)
1157 FN_GLOBAL_STRING(lp_hosts_equiv, &Globals.szHostsEquiv)
1158 FN_GLOBAL_STRING(lp_auto_services, &Globals.szAutoServices)
1159 FN_GLOBAL_STRING(lp_passwd_program, &Globals.szPasswdProgram)
1160 FN_GLOBAL_STRING(lp_passwd_chat, &Globals.szPasswdChat)
1161 FN_GLOBAL_LIST(lp_passwordserver, &Globals.szPasswordServers)
1162 FN_GLOBAL_LIST(lp_name_resolve_order, &Globals.szNameResolveOrder)
1163 FN_GLOBAL_STRING(lp_realm, &Globals.szRealm)
1164 FN_GLOBAL_STRING(lp_ads_server, &Globals.szADSserver)
1165 FN_GLOBAL_STRING(lp_socket_options, &Globals.socket_options)
1166 FN_GLOBAL_STRING(lp_workgroup, &Globals.szWorkgroup)
1167 FN_GLOBAL_STRING(lp_netbios_name, &Globals.szNetbiosName)
1168 FN_GLOBAL_STRING(lp_netbios_scope, &Globals.szNetbiosScope)
1169 FN_GLOBAL_CONST_STRING(lp_logon_script, &Globals.szLogonScript)
1170 FN_GLOBAL_CONST_STRING(lp_logon_path, &Globals.szLogonPath)
1171 FN_GLOBAL_CONST_STRING(lp_logon_drive, &Globals.szLogonDrive)
1172 FN_GLOBAL_CONST_STRING(lp_logon_home, &Globals.szLogonHome)
1173 FN_GLOBAL_STRING(lp_remote_announce, &Globals.szRemoteAnnounce)
1174 FN_GLOBAL_STRING(lp_remote_browse_sync, &Globals.szRemoteBrowseSync)
1175 FN_GLOBAL_LIST(lp_wins_server_list, &Globals.szWINSservers)
1176 FN_GLOBAL_LIST(lp_interfaces, &Globals.szInterfaces)
1177 FN_GLOBAL_STRING(lp_socket_address, &Globals.szSocketAddress)
1178 FN_GLOBAL_LIST(lp_netbios_aliases, &Globals.szNetbiosAliases)
1179 FN_GLOBAL_LIST(lp_preload_modules, &Globals.szPreloadModules)
1180 FN_GLOBAL_STRING(lp_panic_action, &Globals.szPanicAction)
1181 FN_GLOBAL_STRING(lp_adduser_script, &Globals.szAddUserScript)
1182
1183 FN_GLOBAL_CONST_STRING(lp_guestaccount, &Globals.szGuestaccount)
1184
1185 FN_GLOBAL_STRING(lp_addmachine_script, &Globals.szAddMachineScript)
1186
1187 FN_GLOBAL_STRING(lp_wins_hook, &Globals.szWINSHook)
1188 FN_GLOBAL_STRING(lp_wins_partners, &Globals.szWINSPartners)
1189 FN_GLOBAL_STRING(lp_template_homedir, &Globals.szTemplateHomedir)
1190 FN_GLOBAL_STRING(lp_template_shell, &Globals.szTemplateShell)
1191 FN_GLOBAL_CONST_STRING(lp_winbind_separator, &Globals.szWinbindSeparator)
1192 FN_GLOBAL_BOOL(lp_winbind_enum_users, &Globals.bWinbindEnumUsers)
1193 FN_GLOBAL_BOOL(lp_winbind_enum_groups, &Globals.bWinbindEnumGroups)
1194 FN_GLOBAL_BOOL(lp_winbind_use_default_domain, &Globals.bWinbindUseDefaultDomain)
1195 FN_GLOBAL_STRING(lp_idmap_backend, &Globals.szIDMapBackend)
1196
1197 FN_GLOBAL_BOOL(lp_disable_netbios, &Globals.bDisableNetbios)
1198 FN_GLOBAL_BOOL(lp_dns_proxy, &Globals.bDNSproxy)
1199 FN_GLOBAL_BOOL(lp_wins_support, &Globals.bWINSsupport)
1200 FN_GLOBAL_BOOL(lp_we_are_a_wins_server, &Globals.bWINSsupport)
1201 FN_GLOBAL_BOOL(lp_wins_proxy, &Globals.bWINSproxy)
1202 FN_GLOBAL_BOOL(lp_local_master, &Globals.bLocalMaster)
1203 FN_GLOBAL_BOOL(lp_domain_logons, &Globals.bDomainLogons)
1204 FN_GLOBAL_BOOL(lp_load_printers, &Globals.bLoadPrinters)
1205 FN_GLOBAL_BOOL(lp_readraw, &Globals.bReadRaw)
1206 FN_GLOBAL_BOOL(lp_large_readwrite, &Globals.bLargeReadwrite)
1207 FN_GLOBAL_BOOL(lp_writeraw, &Globals.bWriteRaw)
1208 FN_GLOBAL_BOOL(lp_null_passwords, &Globals.bNullPasswords)
1209 FN_GLOBAL_BOOL(lp_obey_pam_restrictions, &Globals.bObeyPamRestrictions)
1210 FN_GLOBAL_BOOL(lp_encrypted_passwords, &Globals.bEncryptPasswords)
1211 static FN_GLOBAL_BOOL(lp_time_server, &Globals.bTimeServer)
1212 FN_GLOBAL_BOOL(lp_bind_interfaces_only, &Globals.bBindInterfacesOnly)
1213 FN_GLOBAL_BOOL(lp_pam_password_change, &Globals.bPamPasswordChange)
1214 FN_GLOBAL_BOOL(lp_unicode, &Globals.bUnicode)
1215 FN_GLOBAL_BOOL(lp_nt_status_support, &Globals.bNTStatusSupport)
1216 FN_GLOBAL_BOOL(lp_allow_trusted_domains, &Globals.bAllowTrustedDomains)
1217 FN_GLOBAL_INTEGER(lp_restrict_anonymous, &Globals.restrict_anonymous)
1218 FN_GLOBAL_BOOL(lp_lanman_auth, &Globals.bLanmanAuth)
1219 FN_GLOBAL_BOOL(lp_ntlm_auth, &Globals.bNTLMAuth)
1220 FN_GLOBAL_BOOL(lp_client_lanman_auth, &Globals.bClientLanManAuth)
1221 FN_GLOBAL_BOOL(lp_client_ntlmv2_auth, &Globals.bClientNTLMv2Auth)
1222 FN_GLOBAL_BOOL(lp_host_msdfs, &Globals.bHostMSDfs)
1223 FN_GLOBAL_BOOL(lp_enhanced_browsing, &Globals.enhanced_browsing)
1224 FN_GLOBAL_BOOL(lp_use_mmap, &Globals.bUseMmap)
1225 FN_GLOBAL_BOOL(lp_unix_extensions, &Globals.bUnixExtensions)
1226 FN_GLOBAL_BOOL(lp_use_spnego, &Globals.bUseSpnego)
1227 FN_GLOBAL_BOOL(lp_hostname_lookups, &Globals.bHostnameLookups)
1228 FN_GLOBAL_BOOL(lp_rpc_big_endian, &Globals.bRpcBigEndian)
1229 FN_GLOBAL_INTEGER(lp_os_level, &Globals.os_level)
1230 FN_GLOBAL_INTEGER(lp_max_ttl, &Globals.max_ttl)
1231 FN_GLOBAL_INTEGER(lp_max_wins_ttl, &Globals.max_wins_ttl)
1232 FN_GLOBAL_INTEGER(lp_min_wins_ttl, &Globals.min_wins_ttl)
1233 FN_GLOBAL_INTEGER(lp_time_offset, &Globals.time_offset)
1234 FN_GLOBAL_INTEGER(lp_maxmux, &Globals.max_mux)
1235 FN_GLOBAL_INTEGER(lp_max_xmit, &Globals.max_xmit)
1236 FN_GLOBAL_INTEGER(lp_passwordlevel, &Globals.pwordlevel)
1237 FN_GLOBAL_INTEGER(lp_usernamelevel, &Globals.unamelevel)
1238 FN_GLOBAL_INTEGER(lp_maxprotocol, &Globals.maxprotocol)
1239 FN_GLOBAL_INTEGER(lp_minprotocol, &Globals.minprotocol)
1240 FN_GLOBAL_INTEGER(lp_security, &Globals.security)
1241 FN_GLOBAL_LIST(lp_auth_methods, &Globals.AuthMethods)
1242 FN_GLOBAL_BOOL(lp_paranoid_server_security, &Globals.paranoid_server_security)
1243 FN_GLOBAL_INTEGER(lp_lpqcachetime, &Globals.lpqcachetime)
1244 FN_GLOBAL_INTEGER(lp_disable_spoolss, &Globals.bDisableSpoolss)
1245 static FN_GLOBAL_INTEGER(lp_announce_as, &Globals.announce_as)
1246 FN_GLOBAL_INTEGER(lp_lm_announce, &Globals.lm_announce)
1247 FN_GLOBAL_INTEGER(lp_lm_interval, &Globals.lm_interval)
1248 FN_GLOBAL_INTEGER(lp_machine_password_timeout, &Globals.machine_password_timeout)
1249 FN_GLOBAL_INTEGER(lp_lock_spin_count, &Globals.iLockSpinCount)
1250 FN_GLOBAL_INTEGER(lp_lock_sleep_time, &Globals.iLockSpinTime)
1251 FN_LOCAL_STRING(lp_servicename, szService)
1252 FN_LOCAL_CONST_STRING(lp_const_servicename, szService)
1253 FN_LOCAL_STRING(lp_pathname, szPath)
1254 FN_LOCAL_STRING(lp_username, szUsername)
1255 FN_LOCAL_LIST(lp_invalid_users, szInvalidUsers)
1256 FN_LOCAL_LIST(lp_valid_users, szValidUsers)
1257 FN_LOCAL_LIST(lp_admin_users, szAdminUsers)
1258 FN_LOCAL_STRING(lp_printcommand, szPrintcommand)
1259 FN_LOCAL_STRING(lp_lpqcommand, szLpqcommand)
1260 FN_LOCAL_STRING(lp_lprmcommand, szLprmcommand)
1261 FN_LOCAL_STRING(lp_lppausecommand, szLppausecommand)
1262 FN_LOCAL_STRING(lp_lpresumecommand, szLpresumecommand)
1263 FN_LOCAL_STRING(lp_queuepausecommand, szQueuepausecommand)
1264 FN_LOCAL_STRING(lp_queueresumecommand, szQueueresumecommand)
1265 static FN_LOCAL_STRING(_lp_printername, szPrintername)
1266 FN_LOCAL_LIST(lp_hostsallow, szHostsallow)
1267 FN_LOCAL_LIST(lp_hostsdeny, szHostsdeny)
1268 FN_LOCAL_STRING(lp_comment, comment)
1269 FN_LOCAL_STRING(lp_fstype, fstype)
1270 FN_LOCAL_STRING(lp_msdfs_proxy, szMSDfsProxy)
1271 static FN_LOCAL_STRING(lp_volume, volume)
1272 FN_LOCAL_LIST(lp_ntvfs_handler, ntvfs_handler)
1273 FN_LOCAL_BOOL(lp_msdfs_root, bMSDfsRoot)
1274 FN_LOCAL_BOOL(lp_autoloaded, autoloaded)
1275 FN_LOCAL_BOOL(lp_browseable, bBrowseable)
1276 FN_LOCAL_BOOL(lp_readonly, bRead_only)
1277 FN_LOCAL_BOOL(lp_guest_ok, bGuest_ok)
1278 FN_LOCAL_BOOL(lp_guest_only, bGuest_only)
1279 FN_LOCAL_BOOL(lp_print_ok, bPrint_ok)
1280 FN_LOCAL_BOOL(lp_map_hidden, bMap_hidden)
1281 FN_LOCAL_BOOL(lp_map_archive, bMap_archive)
1282 FN_LOCAL_BOOL(lp_locking, bLocking)
1283 FN_LOCAL_BOOL(lp_strict_locking, bStrictLocking)
1284 FN_LOCAL_BOOL(lp_posix_locking, bPosixLocking)
1285 FN_LOCAL_BOOL(lp_strict_sync, bStrictSync)
1286 FN_LOCAL_BOOL(lp_ci_filesystem, bCIFileSystem)
1287 FN_LOCAL_BOOL(lp_share_modes, bShareModes)
1288 FN_LOCAL_BOOL(lp_oplocks, bOpLocks)
1289 FN_LOCAL_BOOL(lp_level2_oplocks, bLevel2OpLocks)
1290 FN_LOCAL_BOOL(lp_onlyuser, bOnlyUser)
1291 FN_LOCAL_BOOL(lp_map_system, bMap_system)
1292 FN_LOCAL_INTEGER(lp_max_connections, iMaxConnections)
1293 FN_LOCAL_INTEGER(lp_minprintspace, iMinPrintSpace)
1294 FN_LOCAL_INTEGER(lp_printing, iPrinting)
1295 FN_LOCAL_INTEGER(lp_csc_policy, iCSCPolicy)
1296 FN_GLOBAL_INTEGER(lp_winbind_cache_time, &Globals.winbind_cache_time)
1297 FN_GLOBAL_BOOL(lp_hide_local_users, &Globals.bHideLocalUsers)
1298 FN_GLOBAL_INTEGER(lp_name_cache_timeout, &Globals.name_cache_timeout)
1299 FN_GLOBAL_INTEGER(lp_server_signing, &Globals.server_signing)
1300 FN_GLOBAL_INTEGER(lp_client_signing, &Globals.client_signing)
1301
1302 /* local prototypes */
1303
1304 static int map_parameter(const char *pszParmName);
1305 static BOOL set_boolean(BOOL *pb, const char *pszParmValue);
1306 static int getservicebyname(const char *pszServiceName,
1307                             service * pserviceDest);
1308 static void copy_service(service * pserviceDest,
1309                          service * pserviceSource, BOOL *pcopymapDest);
1310 static BOOL service_ok(int iService);
1311 static BOOL do_section(const char *pszSectionName);
1312 static void init_copymap(service * pservice);
1313
1314 /* This is a helper function for parametrical options support. */
1315 /* It returns a pointer to parametrical option value if it exists or NULL otherwise */
1316 /* Actual parametrical functions are quite simple */
1317 const char *lp_get_parametric(int lookup_service, const char *type, const char *option)
1318 {
1319         char *vfskey;
1320         struct param_opt *data;
1321         
1322         if (lookup_service >= iNumServices) return NULL;
1323         
1324         data = (lookup_service < 0) ? 
1325                 Globals.param_opt : ServicePtrs[lookup_service]->param_opt;
1326     
1327         asprintf(&vfskey, "%s:%s", type, option);
1328         strlower(vfskey);
1329
1330         while (data) {
1331                 if (strcmp(data->key, vfskey) == 0) {
1332                         free(vfskey);
1333                         return data->value;
1334                 }
1335                 data = data->next;
1336         }
1337
1338         if (lookup_service >= 0) {
1339                 /* Try to fetch the same option but from globals */
1340                 /* but only if we are not already working with Globals */
1341                 data = Globals.param_opt;
1342                 while (data) {
1343                         if (strcmp(data->key, vfskey) == 0) {
1344                                 free(vfskey);
1345                                 return data->value;
1346                         }
1347                         data = data->next;
1348                 }
1349         }
1350
1351         free(vfskey);
1352         
1353         return NULL;
1354 }
1355
1356
1357 /*******************************************************************
1358 convenience routine to return int parameters.
1359 ********************************************************************/
1360 static int lp_int(const char *s)
1361 {
1362
1363         if (!s) {
1364                 DEBUG(0,("lp_int(%s): is called with NULL!\n",s));
1365                 return (-1);
1366         }
1367
1368         return atoi(s); 
1369 }
1370
1371 /*******************************************************************
1372 convenience routine to return unsigned long parameters.
1373 ********************************************************************/
1374 static int lp_ulong(const char *s)
1375 {
1376
1377         if (!s) {
1378                 DEBUG(0,("lp_int(%s): is called with NULL!\n",s));
1379                 return (-1);
1380         }
1381
1382         return strtoul(s, NULL, 10);
1383 }
1384
1385 /*******************************************************************
1386 convenience routine to return boolean parameters.
1387 ********************************************************************/
1388 static BOOL lp_bool(const char *s)
1389 {
1390         BOOL ret = False;
1391
1392         if (!s) {
1393                 DEBUG(0,("lp_bool(%s): is called with NULL!\n",s));
1394                 return False;
1395         }
1396         
1397         if (!set_boolean(&ret,s)) {
1398                 DEBUG(0,("lp_bool(%s): value is not boolean!\n",s));
1399                 return False;
1400         }
1401
1402         return ret;
1403 }
1404
1405
1406 /* Return parametric option from a given service. Type is a part of option before ':' */
1407 /* Parametric option has following syntax: 'Type: option = value' */
1408 /* Returned value is allocated in 'lp_talloc' context */
1409
1410 const char *lp_parm_string(int lookup_service, const char *type, const char *option)
1411 {
1412         const char *value = lp_get_parametric(lookup_service, type, option);
1413
1414         if (value)
1415                 return lp_string(value);
1416
1417         return NULL;
1418 }
1419
1420 /* Return parametric option from a given service. Type is a part of option before ':' */
1421 /* Parametric option has following syntax: 'Type: option = value' */
1422 /* Returned value is allocated in 'lp_talloc' context */
1423
1424 const char **lp_parm_string_list(int lookup_service, const char *type, const char *option,
1425                                  const char *separator)
1426 {
1427         const char *value = lp_get_parametric(lookup_service, type, option);
1428         
1429         if (value)
1430                 return str_list_make(talloc_autofree_context(), value, separator);
1431
1432         return NULL;
1433 }
1434
1435 /* Return parametric option from a given service. Type is a part of option before ':' */
1436 /* Parametric option has following syntax: 'Type: option = value' */
1437
1438 int lp_parm_int(int lookup_service, const char *type, const char *option, int default_v)
1439 {
1440         const char *value = lp_get_parametric(lookup_service, type, option);
1441         
1442         if (value)
1443                 return lp_int(value);
1444
1445         return default_v;
1446 }
1447
1448 /* Return parametric option from a given service. Type is a part of option before ':' */
1449 /* Parametric option has following syntax: 'Type: option = value' */
1450
1451 unsigned long lp_parm_ulong(int lookup_service, const char *type, const char *option, unsigned long default_v)
1452 {
1453         const char *value = lp_get_parametric(lookup_service, type, option);
1454         
1455         if (value)
1456                 return lp_ulong(value);
1457
1458         return default_v;
1459 }
1460
1461 /* Return parametric option from a given service. Type is a part of option before ':' */
1462 /* Parametric option has following syntax: 'Type: option = value' */
1463
1464 BOOL lp_parm_bool(int lookup_service, const char *type, const char *option, BOOL default_v)
1465 {
1466         const char *value = lp_get_parametric(lookup_service, type, option);
1467         
1468         if (value)
1469                 return lp_bool(value);
1470
1471         return default_v;
1472 }
1473
1474
1475 /***************************************************************************
1476  Initialise a service to the defaults.
1477 ***************************************************************************/
1478
1479 static void init_service(service * pservice)
1480 {
1481         memset((char *)pservice, '\0', sizeof(service));
1482         copy_service(pservice, &sDefault, NULL);
1483 }
1484
1485 /***************************************************************************
1486  Free the dynamically allocated parts of a service struct.
1487 ***************************************************************************/
1488
1489 static void free_service(service *pservice)
1490 {
1491         int i;
1492         struct param_opt *data, *pdata;
1493         if (!pservice)
1494                 return;
1495
1496         if (pservice->szService)
1497                 DEBUG(5, ("free_service: Freeing service %s\n",
1498                        pservice->szService));
1499
1500         string_free(&pservice->szService);
1501         SAFE_FREE(pservice->copymap);
1502
1503         for (i = 0; parm_table[i].label; i++) {
1504                 if ((parm_table[i].type == P_STRING ||
1505                      parm_table[i].type == P_USTRING) &&
1506                     parm_table[i].class == P_LOCAL) {
1507                         string_free((char **)
1508                                     (((char *)pservice) +
1509                                      PTR_DIFF(parm_table[i].ptr, &sDefault)));
1510                 } else if (parm_table[i].type == P_LIST &&
1511                            parm_table[i].class == P_LOCAL) {
1512                         char ***listp = (char ***)(((char *)pservice) + 
1513                                                    PTR_DIFF(parm_table[i].ptr, &sDefault));
1514                         talloc_free(*listp);
1515                         *listp = NULL;
1516                 }
1517         }
1518                                 
1519         DEBUG(5,("Freeing parametrics:\n"));
1520         data = pservice->param_opt;
1521         while (data) {
1522                 DEBUG(5,("[%s = %s]\n", data->key, data->value));
1523                 string_free(&data->key);
1524                 string_free(&data->value);
1525                 pdata = data->next;
1526                 SAFE_FREE(data);
1527                 data = pdata;
1528         }
1529
1530         ZERO_STRUCTP(pservice);
1531 }
1532
1533 /***************************************************************************
1534  Add a new service to the services array initialising it with the given 
1535  service. 
1536 ***************************************************************************/
1537
1538 static int add_a_service(const service *pservice, const char *name)
1539 {
1540         int i;
1541         service tservice;
1542         int num_to_alloc = iNumServices + 1;
1543         struct param_opt *data, *pdata;
1544
1545         tservice = *pservice;
1546
1547         /* it might already exist */
1548         if (name) {
1549                 i = getservicebyname(name, NULL);
1550                 if (i >= 0) {
1551                         /* Clean all parametric options for service */
1552                         /* They will be added during parsing again */
1553                         data = ServicePtrs[i]->param_opt;
1554                         while (data) {
1555                                 string_free(&data->key);
1556                                 string_free(&data->value);
1557                                 pdata = data->next;
1558                                 SAFE_FREE(data);
1559                                 data = pdata;
1560                         }
1561                         ServicePtrs[i]->param_opt = NULL;
1562                         return (i);
1563                 }
1564         }
1565
1566         /* find an invalid one */
1567         for (i = 0; i < iNumServices; i++)
1568                 if (!ServicePtrs[i]->valid)
1569                         break;
1570
1571         /* if not, then create one */
1572         if (i == iNumServices) {
1573                 service **tsp;
1574                 
1575                 tsp = realloc_p(ServicePtrs, service *, num_to_alloc);
1576                                            
1577                 if (!tsp) {
1578                         DEBUG(0,("add_a_service: failed to enlarge ServicePtrs!\n"));
1579                         return (-1);
1580                 }
1581                 else {
1582                         ServicePtrs = tsp;
1583                         ServicePtrs[iNumServices] = malloc_p(service);
1584                 }
1585                 if (!ServicePtrs[iNumServices]) {
1586                         DEBUG(0,("add_a_service: out of memory!\n"));
1587                         return (-1);
1588                 }
1589
1590                 iNumServices++;
1591         } else
1592                 free_service(ServicePtrs[i]);
1593
1594         ServicePtrs[i]->valid = True;
1595
1596         init_service(ServicePtrs[i]);
1597         copy_service(ServicePtrs[i], &tservice, NULL);
1598         if (name)
1599                 string_set(&ServicePtrs[i]->szService, name);
1600         return (i);
1601 }
1602
1603 /***************************************************************************
1604  Add a new home service, with the specified home directory, defaults coming 
1605  from service ifrom.
1606 ***************************************************************************/
1607
1608 BOOL lp_add_home(const char *pszHomename, int iDefaultService, 
1609                  const char *user, const char *pszHomedir)
1610 {
1611         int i;
1612         pstring newHomedir;
1613
1614         i = add_a_service(ServicePtrs[iDefaultService], pszHomename);
1615
1616         if (i < 0)
1617                 return (False);
1618
1619         if (!(*(ServicePtrs[iDefaultService]->szPath))
1620             || strequal(ServicePtrs[iDefaultService]->szPath, lp_pathname(-1))) {
1621                 pstrcpy(newHomedir, pszHomedir);
1622         } else {
1623                 pstrcpy(newHomedir, lp_pathname(iDefaultService));
1624                 string_sub(newHomedir,"%H", pszHomedir, sizeof(newHomedir)); 
1625         }
1626
1627         string_set(&ServicePtrs[i]->szPath, newHomedir);
1628
1629         if (!(*(ServicePtrs[i]->comment))) {
1630                 pstring comment;
1631                 slprintf(comment, sizeof(comment) - 1,
1632                          "Home directory of %s", user);
1633                 string_set(&ServicePtrs[i]->comment, comment);
1634         }
1635         ServicePtrs[i]->bAvailable = sDefault.bAvailable;
1636         ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
1637
1638         DEBUG(3, ("adding home's share [%s] for user '%s' at '%s'\n", pszHomename, 
1639                user, newHomedir));
1640         
1641         return (True);
1642 }
1643
1644 /***************************************************************************
1645  Add a new service, based on an old one.
1646 ***************************************************************************/
1647
1648 int lp_add_service(const char *pszService, int iDefaultService)
1649 {
1650         return (add_a_service(ServicePtrs[iDefaultService], pszService));
1651 }
1652
1653 /***************************************************************************
1654  Add the IPC service.
1655 ***************************************************************************/
1656
1657 static BOOL lp_add_hidden(const char *name, const char *fstype, BOOL guest_ok)
1658 {
1659         pstring comment;
1660         int i = add_a_service(&sDefault, name);
1661
1662         if (i < 0)
1663                 return (False);
1664
1665         slprintf(comment, sizeof(comment) - 1,
1666                  "%s Service (%s)", fstype, Globals.szServerString);
1667
1668         string_set(&ServicePtrs[i]->szPath, tmpdir());
1669         string_set(&ServicePtrs[i]->szUsername, "");
1670         string_set(&ServicePtrs[i]->comment, comment);
1671         string_set(&ServicePtrs[i]->fstype, fstype);
1672         ServicePtrs[i]->iMaxConnections = -1;
1673         ServicePtrs[i]->bAvailable = True;
1674         ServicePtrs[i]->bRead_only = True;
1675         ServicePtrs[i]->bGuest_only = False;
1676         ServicePtrs[i]->bGuest_ok = guest_ok;
1677         ServicePtrs[i]->bPrint_ok = False;
1678         ServicePtrs[i]->bBrowseable = False;
1679
1680         if (strcasecmp(fstype, "IPC") == 0) {
1681                 lp_do_parameter(i, "ntvfs handler", "default");
1682         }
1683
1684         DEBUG(3, ("adding hidden service %s\n", name));
1685
1686         return (True);
1687 }
1688
1689 /***************************************************************************
1690  Add a new printer service, with defaults coming from service iFrom.
1691 ***************************************************************************/
1692
1693 BOOL lp_add_printer(const char *pszPrintername, int iDefaultService)
1694 {
1695         const char *comment = "From Printcap";
1696         int i = add_a_service(ServicePtrs[iDefaultService], pszPrintername);
1697
1698         if (i < 0)
1699                 return (False);
1700
1701         /* note that we do NOT default the availability flag to True - */
1702         /* we take it from the default service passed. This allows all */
1703         /* dynamic printers to be disabled by disabling the [printers] */
1704         /* entry (if/when the 'available' keyword is implemented!).    */
1705
1706         /* the printer name is set to the service name. */
1707         string_set(&ServicePtrs[i]->szPrintername, pszPrintername);
1708         string_set(&ServicePtrs[i]->comment, comment);
1709         ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
1710         /* Printers cannot be read_only. */
1711         ServicePtrs[i]->bRead_only = False;
1712         /* No share modes on printer services. */
1713         ServicePtrs[i]->bShareModes = False;
1714         /* No oplocks on printer services. */
1715         ServicePtrs[i]->bOpLocks = False;
1716         /* Printer services must be printable. */
1717         ServicePtrs[i]->bPrint_ok = True;
1718
1719         DEBUG(3, ("adding printer service %s\n", pszPrintername));
1720
1721         update_server_announce_as_printserver();
1722
1723         return (True);
1724 }
1725
1726 /***************************************************************************
1727  Map a parameter's string representation to something we can use. 
1728  Returns False if the parameter string is not recognised, else TRUE.
1729 ***************************************************************************/
1730
1731 static int map_parameter(const char *pszParmName)
1732 {
1733         int iIndex;
1734
1735         if (*pszParmName == '-')
1736                 return (-1);
1737
1738         for (iIndex = 0; parm_table[iIndex].label; iIndex++)
1739                 if (strwicmp(parm_table[iIndex].label, pszParmName) == 0)
1740                         return (iIndex);
1741
1742         /* Warn only if it isn't parametric option */
1743         if (strchr(pszParmName, ':') == NULL)
1744                 DEBUG(0, ("Unknown parameter encountered: \"%s\"\n", pszParmName));
1745         /* We do return 'fail' for parametric options as well because they are
1746            stored in different storage
1747          */
1748         return (-1);
1749 }
1750
1751
1752 /*
1753   return the parameter structure for a parameter
1754 */
1755 struct parm_struct *lp_parm_struct(const char *name)
1756 {
1757         int parmnum = map_parameter(name);
1758         if (parmnum == -1) return NULL;
1759         return &parm_table[parmnum];
1760 }
1761
1762 /*
1763   return the parameter pointer for a parameter
1764 */
1765 void *lp_parm_ptr(int snum, struct parm_struct *parm)
1766 {
1767         if (snum == -1) {
1768                 return parm->ptr;
1769         }
1770         return ((char *)ServicePtrs[snum]) + PTR_DIFF(parm->ptr, &sDefault);
1771 }
1772
1773 /***************************************************************************
1774  Set a boolean variable from the text value stored in the passed string.
1775  Returns True in success, False if the passed string does not correctly 
1776  represent a boolean.
1777 ***************************************************************************/
1778
1779 static BOOL set_boolean(BOOL *pb, const char *pszParmValue)
1780 {
1781         BOOL bRetval;
1782
1783         bRetval = True;
1784         if (strwicmp(pszParmValue, "yes") == 0 ||
1785             strwicmp(pszParmValue, "true") == 0 ||
1786             strwicmp(pszParmValue, "1") == 0)
1787                 *pb = True;
1788         else if (strwicmp(pszParmValue, "no") == 0 ||
1789                     strwicmp(pszParmValue, "False") == 0 ||
1790                     strwicmp(pszParmValue, "0") == 0)
1791                 *pb = False;
1792         else {
1793                 DEBUG(0,
1794                       ("ERROR: Badly formed boolean in configuration file: \"%s\".\n",
1795                        pszParmValue));
1796                 bRetval = False;
1797         }
1798         return (bRetval);
1799 }
1800
1801 /***************************************************************************
1802 Find a service by name. Otherwise works like get_service.
1803 ***************************************************************************/
1804
1805 static int getservicebyname(const char *pszServiceName, service * pserviceDest)
1806 {
1807         int iService;
1808
1809         for (iService = iNumServices - 1; iService >= 0; iService--)
1810                 if (VALID(iService) &&
1811                     strwicmp(ServicePtrs[iService]->szService, pszServiceName) == 0) {
1812                         if (pserviceDest != NULL)
1813                                 copy_service(pserviceDest, ServicePtrs[iService], NULL);
1814                         break;
1815                 }
1816
1817         return (iService);
1818 }
1819
1820 /***************************************************************************
1821  Copy a service structure to another.
1822  If pcopymapDest is NULL then copy all fields
1823 ***************************************************************************/
1824
1825 static void copy_service(service * pserviceDest, service * pserviceSource, BOOL *pcopymapDest)
1826 {
1827         int i;
1828         BOOL bcopyall = (pcopymapDest == NULL);
1829         struct param_opt *data, *pdata, *paramo;
1830         BOOL not_added;
1831
1832         for (i = 0; parm_table[i].label; i++)
1833                 if (parm_table[i].ptr && parm_table[i].class == P_LOCAL &&
1834                     (bcopyall || pcopymapDest[i])) {
1835                         void *def_ptr = parm_table[i].ptr;
1836                         void *src_ptr =
1837                                 ((char *)pserviceSource) + PTR_DIFF(def_ptr,
1838                                                                     &sDefault);
1839                         void *dest_ptr =
1840                                 ((char *)pserviceDest) + PTR_DIFF(def_ptr,
1841                                                                   &sDefault);
1842
1843                         switch (parm_table[i].type) {
1844                                 case P_BOOL:
1845                                         *(BOOL *)dest_ptr = *(BOOL *)src_ptr;
1846                                         break;
1847
1848                                 case P_INTEGER:
1849                                 case P_ENUM:
1850                                         *(int *)dest_ptr = *(int *)src_ptr;
1851                                         break;
1852
1853                                 case P_STRING:
1854                                         string_set(dest_ptr,
1855                                                    *(char **)src_ptr);
1856                                         break;
1857
1858                                 case P_USTRING:
1859                                         string_set(dest_ptr,
1860                                                    *(char **)src_ptr);
1861                                         strupper(*(char **)dest_ptr);
1862                                         break;
1863                                 case P_LIST:
1864                                         *(const char ***)dest_ptr = str_list_copy(talloc_autofree_context(), 
1865                                                                                   *(const char ***)src_ptr);
1866                                         break;
1867                                 default:
1868                                         break;
1869                         }
1870                 }
1871
1872         if (bcopyall) {
1873                 init_copymap(pserviceDest);
1874                 if (pserviceSource->copymap)
1875                         memcpy((void *)pserviceDest->copymap,
1876                                (void *)pserviceSource->copymap,
1877                                sizeof(BOOL) * NUMPARAMETERS);
1878         }
1879         
1880         data = pserviceSource->param_opt;
1881         while (data) {
1882                 not_added = True;
1883                 pdata = pserviceDest->param_opt;
1884                 /* Traverse destination */
1885                 while (pdata) {
1886                         /* If we already have same option, override it */
1887                         if (strcmp(pdata->key, data->key) == 0) {
1888                                 string_free(&pdata->value);
1889                                 pdata->value = strdup(data->value);
1890                                 not_added = False;
1891                                 break;
1892                         }
1893                         pdata = pdata->next;
1894                 }
1895                 if (not_added) {
1896                         paramo = smb_xmalloc_p(struct param_opt);
1897                         paramo->key = strdup(data->key);
1898                         paramo->value = strdup(data->value);
1899                         DLIST_ADD(pserviceDest->param_opt, paramo);
1900                 }
1901                 data = data->next;
1902         }
1903 }
1904
1905 /***************************************************************************
1906 Check a service for consistency. Return False if the service is in any way
1907 incomplete or faulty, else True.
1908 ***************************************************************************/
1909
1910 static BOOL service_ok(int iService)
1911 {
1912         BOOL bRetval;
1913
1914         bRetval = True;
1915         if (ServicePtrs[iService]->szService[0] == '\0') {
1916                 DEBUG(0, ("The following message indicates an internal error:\n"));
1917                 DEBUG(0, ("No service name in service entry.\n"));
1918                 bRetval = False;
1919         }
1920
1921         /* The [printers] entry MUST be printable. I'm all for flexibility, but */
1922         /* I can't see why you'd want a non-printable printer service...        */
1923         if (strwicmp(ServicePtrs[iService]->szService, PRINTERS_NAME) == 0) {
1924                 if (!ServicePtrs[iService]->bPrint_ok) {
1925                         DEBUG(0, ("WARNING: [%s] service MUST be printable!\n",
1926                                ServicePtrs[iService]->szService));
1927                         ServicePtrs[iService]->bPrint_ok = True;
1928                         update_server_announce_as_printserver();
1929                 }
1930                 /* [printers] service must also be non-browsable. */
1931                 if (ServicePtrs[iService]->bBrowseable)
1932                         ServicePtrs[iService]->bBrowseable = False;
1933         }
1934
1935         /* If a service is flagged unavailable, log the fact at level 0. */
1936         if (!ServicePtrs[iService]->bAvailable)
1937                 DEBUG(1, ("NOTE: Service %s is flagged unavailable.\n",
1938                           ServicePtrs[iService]->szService));
1939
1940         return (bRetval);
1941 }
1942
1943 static struct file_lists {
1944         struct file_lists *next;
1945         char *name;
1946         char *subfname;
1947         time_t modtime;
1948 } *file_lists = NULL;
1949
1950 /*******************************************************************
1951  Keep a linked list of all config files so we know when one has changed 
1952  it's date and needs to be reloaded.
1953 ********************************************************************/
1954
1955 static void add_to_file_list(const char *fname, const char *subfname)
1956 {
1957         struct file_lists *f = file_lists;
1958
1959         while (f) {
1960                 if (f->name && !strcmp(f->name, fname))
1961                         break;
1962                 f = f->next;
1963         }
1964
1965         if (!f) {
1966                 f = malloc_p(struct file_lists);
1967                 if (!f)
1968                         return;
1969                 f->next = file_lists;
1970                 f->name = strdup(fname);
1971                 if (!f->name) {
1972                         SAFE_FREE(f);
1973                         return;
1974                 }
1975                 f->subfname = strdup(subfname);
1976                 if (!f->subfname) {
1977                         SAFE_FREE(f);
1978                         return;
1979                 }
1980                 file_lists = f;
1981                 f->modtime = file_modtime(subfname);
1982         } else {
1983                 time_t t = file_modtime(subfname);
1984                 if (t)
1985                         f->modtime = t;
1986         }
1987 }
1988
1989 /*******************************************************************
1990  Check if a config file has changed date.
1991 ********************************************************************/
1992
1993 BOOL lp_file_list_changed(void)
1994 {
1995         struct file_lists *f = file_lists;
1996         DEBUG(6, ("lp_file_list_changed()\n"));
1997
1998         while (f) {
1999                 pstring n2;
2000                 time_t mod_time;
2001
2002                 pstrcpy(n2, f->name);
2003                 standard_sub_basic(n2,sizeof(n2));
2004
2005                 DEBUGADD(6, ("file %s -> %s  last mod_time: %s\n",
2006                              f->name, n2, ctime(&f->modtime)));
2007
2008                 mod_time = file_modtime(n2);
2009
2010                 if (mod_time && ((f->modtime != mod_time) || (f->subfname == NULL) || (strcmp(n2, f->subfname) != 0))) {
2011                         DEBUGADD(6,
2012                                  ("file %s modified: %s\n", n2,
2013                                   ctime(&mod_time)));
2014                         f->modtime = mod_time;
2015                         SAFE_FREE(f->subfname);
2016                         f->subfname = strdup(n2);
2017                         return (True);
2018                 }
2019                 f = f->next;
2020         }
2021         return (False);
2022 }
2023
2024 /***************************************************************************
2025  Handle the include operation.
2026 ***************************************************************************/
2027
2028 static BOOL handle_include(const char *pszParmValue, char **ptr)
2029 {
2030         pstring fname;
2031         pstrcpy(fname, pszParmValue);
2032
2033         standard_sub_basic(fname,sizeof(fname));
2034
2035         add_to_file_list(pszParmValue, fname);
2036
2037         string_set(ptr, fname);
2038
2039         if (file_exist(fname))
2040                 return (pm_process(fname, do_section, do_parameter));
2041
2042         DEBUG(2, ("Can't find include file %s\n", fname));
2043
2044         return (False);
2045 }
2046
2047 /***************************************************************************
2048  Handle the interpretation of the copy parameter.
2049 ***************************************************************************/
2050
2051 static BOOL handle_copy(const char *pszParmValue, char **ptr)
2052 {
2053         BOOL bRetval;
2054         int iTemp;
2055         service serviceTemp;
2056
2057         string_set(ptr, pszParmValue);
2058
2059         init_service(&serviceTemp);
2060
2061         bRetval = False;
2062
2063         DEBUG(3, ("Copying service from service %s\n", pszParmValue));
2064
2065         if ((iTemp = getservicebyname(pszParmValue, &serviceTemp)) >= 0) {
2066                 if (iTemp == iServiceIndex) {
2067                         DEBUG(0, ("Can't copy service %s - unable to copy self!\n", pszParmValue));
2068                 } else {
2069                         copy_service(ServicePtrs[iServiceIndex],
2070                                      &serviceTemp,
2071                                      ServicePtrs[iServiceIndex]->copymap);
2072                         bRetval = True;
2073                 }
2074         } else {
2075                 DEBUG(0, ("Unable to copy service - source not found: %s\n", pszParmValue));
2076                 bRetval = False;
2077         }
2078
2079         free_service(&serviceTemp);
2080         return (bRetval);
2081 }
2082
2083 /***************************************************************************
2084  Handle winbind/non unix account uid and gid allocation parameters.  The format of these
2085  parameters is:
2086
2087  [global]
2088
2089         winbind uid = 1000-1999
2090         winbind gid = 700-899
2091
2092  We only do simple parsing checks here.  The strings are parsed into useful
2093  structures in the winbind daemon code.
2094
2095 ***************************************************************************/
2096
2097 /* Some lp_ routines to return winbind [ug]id information */
2098
2099 static uid_t winbind_uid_low, winbind_uid_high;
2100 static gid_t winbind_gid_low, winbind_gid_high;
2101 static uint32_t non_unix_account_low, non_unix_account_high;
2102
2103 BOOL lp_winbind_uid(uid_t *low, uid_t *high)
2104 {
2105         if (winbind_uid_low == 0 || winbind_uid_high == 0)
2106                 return False;
2107
2108         if (low)
2109                 *low = winbind_uid_low;
2110
2111         if (high)
2112                 *high = winbind_uid_high;
2113
2114         return True;
2115 }
2116
2117 BOOL lp_winbind_gid(gid_t *low, gid_t *high)
2118 {
2119         if (winbind_gid_low == 0 || winbind_gid_high == 0)
2120                 return False;
2121
2122         if (low)
2123                 *low = winbind_gid_low;
2124
2125         if (high)
2126                 *high = winbind_gid_high;
2127
2128         return True;
2129 }
2130
2131 BOOL lp_non_unix_account_range(uint32_t *low, uint32_t *high)
2132 {
2133         if (non_unix_account_low == 0 || non_unix_account_high == 0)
2134                 return False;
2135
2136         if (low)
2137                 *low = non_unix_account_low;
2138
2139         if (high)
2140                 *high = non_unix_account_high;
2141
2142         return True;
2143 }
2144
2145 /* Do some simple checks on "winbind [ug]id" parameter values */
2146
2147 static BOOL handle_winbind_uid(const char *pszParmValue, char **ptr)
2148 {
2149         uint32_t low, high;
2150
2151         if (sscanf(pszParmValue, "%u-%u", &low, &high) != 2 || high < low)
2152                 return False;
2153
2154         /* Parse OK */
2155
2156         string_set(ptr, pszParmValue);
2157
2158         winbind_uid_low = low;
2159         winbind_uid_high = high;
2160
2161         return True;
2162 }
2163
2164 static BOOL handle_winbind_gid(const char *pszParmValue, char **ptr)
2165 {
2166         uint32_t low, high;
2167
2168         if (sscanf(pszParmValue, "%u-%u", &low, &high) != 2 || high < low)
2169                 return False;
2170
2171         /* Parse OK */
2172
2173         string_set(ptr, pszParmValue);
2174
2175         winbind_gid_low = low;
2176         winbind_gid_high = high;
2177
2178         return True;
2179 }
2180
2181 /***************************************************************************
2182  Do some simple checks on "non unix account range" parameter values.
2183 ***************************************************************************/
2184
2185 static BOOL handle_non_unix_account_range(const char *pszParmValue, char **ptr)
2186 {
2187         uint32_t low, high;
2188
2189         if (sscanf(pszParmValue, "%u-%u", &low, &high) != 2 || high < low)
2190                 return False;
2191
2192         /* Parse OK */
2193
2194         string_set(ptr, pszParmValue);
2195
2196         non_unix_account_low = low;
2197         non_unix_account_high = high;
2198
2199         return True;
2200 }
2201
2202
2203 /***************************************************************************
2204  Initialise a copymap.
2205 ***************************************************************************/
2206
2207 static void init_copymap(service * pservice)
2208 {
2209         int i;
2210         SAFE_FREE(pservice->copymap);
2211         pservice->copymap = malloc_array_p(BOOL, NUMPARAMETERS);
2212         if (!pservice->copymap)
2213                 DEBUG(0,
2214                       ("Couldn't allocate copymap!! (size %d)\n",
2215                        (int)NUMPARAMETERS));
2216         else
2217                 for (i = 0; i < NUMPARAMETERS; i++)
2218                         pservice->copymap[i] = True;
2219 }
2220
2221 /***************************************************************************
2222  Return the local pointer to a parameter given the service number and the 
2223  pointer into the default structure.
2224 ***************************************************************************/
2225
2226 void *lp_local_ptr(int snum, void *ptr)
2227 {
2228         return (void *)(((char *)ServicePtrs[snum]) + PTR_DIFF(ptr, &sDefault));
2229 }
2230
2231
2232 /***************************************************************************
2233  Process a parametric option
2234 ***************************************************************************/
2235 static BOOL lp_do_parameter_parametric(int snum, const char *pszParmName, const char *pszParmValue, int flags)
2236 {
2237         struct param_opt *paramo, *data;
2238         char *name;
2239
2240         while (isspace(*pszParmName)) {
2241                 pszParmName++;
2242         }
2243
2244         name = strdup(pszParmName);
2245         if (!name) return False;
2246
2247         strlower(name);
2248
2249         if (snum < 0) {
2250                 data = Globals.param_opt;
2251         } else {
2252                 data = ServicePtrs[snum]->param_opt;
2253         }
2254
2255         /* Traverse destination */
2256         for (paramo=data; paramo; paramo=paramo->next) {
2257                 /* If we already have the option set, override it unless
2258                    it was a command line option and the new one isn't */
2259                 if (strcmp(paramo->key, name) == 0) {
2260                         if ((paramo->flags & FLAG_CMDLINE) &&
2261                             !(flags & FLAG_CMDLINE)) {
2262                                 return True;
2263                         }
2264
2265                         free(paramo->value);
2266                         paramo->value = strdup(pszParmValue);
2267                         paramo->flags = flags;
2268                         free(name);
2269                         return True;
2270                 }
2271         }
2272
2273         paramo = smb_xmalloc_p(struct param_opt);
2274         paramo->key = strdup(name);
2275         paramo->value = strdup(pszParmValue);
2276         paramo->flags = flags;
2277         if (snum < 0) {
2278                 DLIST_ADD(Globals.param_opt, paramo);
2279         } else {
2280                 DLIST_ADD(ServicePtrs[snum]->param_opt, paramo);
2281         }
2282
2283         free(name);
2284         
2285         return True;
2286 }
2287
2288 /***************************************************************************
2289  Process a parameter for a particular service number. If snum < 0
2290  then assume we are in the globals.
2291 ***************************************************************************/
2292 BOOL lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue)
2293 {
2294         int parmnum, i;
2295         void *parm_ptr = NULL;  /* where we are going to store the result */
2296         void *def_ptr = NULL;
2297
2298         parmnum = map_parameter(pszParmName);
2299
2300         if (parmnum < 0) {
2301                 if (strchr(pszParmName, ':')) {
2302                         return lp_do_parameter_parametric(snum, pszParmName, pszParmValue, 0);
2303                 }
2304                 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n", pszParmName));
2305                 return (True);
2306         }
2307
2308         if (parm_table[parmnum].flags & FLAG_DEPRECATED) {
2309                 DEBUG(1, ("WARNING: The \"%s\" option is deprecated\n",
2310                           pszParmName));
2311         }
2312
2313         /* if the flag has been set on the command line, then don't allow override,
2314            but don't report an error */
2315         if (parm_table[parmnum].flags & FLAG_CMDLINE) {
2316                 return True;
2317         }
2318
2319         def_ptr = parm_table[parmnum].ptr;
2320
2321         /* we might point at a service, the default service or a global */
2322         if (snum < 0) {
2323                 parm_ptr = def_ptr;
2324         } else {
2325                 if (parm_table[parmnum].class == P_GLOBAL) {
2326                         DEBUG(0,
2327                               ("Global parameter %s found in service section!\n",
2328                                pszParmName));
2329                         return (True);
2330                 }
2331                 parm_ptr =
2332                         ((char *)ServicePtrs[snum]) + PTR_DIFF(def_ptr,
2333                                                             &sDefault);
2334         }
2335
2336         if (snum >= 0) {
2337                 if (!ServicePtrs[snum]->copymap)
2338                         init_copymap(ServicePtrs[snum]);
2339
2340                 /* this handles the aliases - set the copymap for other entries with
2341                    the same data pointer */
2342                 for (i = 0; parm_table[i].label; i++)
2343                         if (parm_table[i].ptr == parm_table[parmnum].ptr)
2344                                 ServicePtrs[snum]->copymap[i] = False;
2345         }
2346
2347         /* if it is a special case then go ahead */
2348         if (parm_table[parmnum].special) {
2349                 parm_table[parmnum].special(pszParmValue, (char **)parm_ptr);
2350                 return (True);
2351         }
2352
2353         /* now switch on the type of variable it is */
2354         switch (parm_table[parmnum].type)
2355         {
2356                 case P_BOOL:
2357                         set_boolean(parm_ptr, pszParmValue);
2358                         break;
2359
2360                 case P_INTEGER:
2361                         *(int *)parm_ptr = atoi(pszParmValue);
2362                         break;
2363
2364                 case P_LIST:
2365                         *(const char ***)parm_ptr = str_list_make(talloc_autofree_context(), 
2366                                                                   pszParmValue, NULL);
2367                         break;
2368
2369                 case P_STRING:
2370                         string_set(parm_ptr, pszParmValue);
2371                         break;
2372
2373                 case P_USTRING:
2374                         string_set(parm_ptr, pszParmValue);
2375                         strupper(*(char **)parm_ptr);
2376                         break;
2377
2378                 case P_ENUM:
2379                         for (i = 0; parm_table[parmnum].enum_list[i].name; i++) {
2380                                 if (strequal
2381                                     (pszParmValue,
2382                                      parm_table[parmnum].enum_list[i].name)) {
2383                                         *(int *)parm_ptr =
2384                                                 parm_table[parmnum].
2385                                                 enum_list[i].value;
2386                                         break;
2387                                 }
2388                         }
2389                         if (!parm_table[parmnum].enum_list[i].name) {
2390                                 DEBUG(0,("Unknown enumerated value '%s' for '%s'\n", 
2391                                          pszParmValue, pszParmName));
2392                                 return False;
2393                         }
2394                         break;
2395                 case P_SEP:
2396                         break;
2397         }
2398
2399         return (True);
2400 }
2401
2402 /***************************************************************************
2403  Process a parameter.
2404 ***************************************************************************/
2405
2406 static BOOL do_parameter(const char *pszParmName, const char *pszParmValue)
2407 {
2408         if (!bInGlobalSection && bGlobalOnly)
2409                 return (True);
2410
2411         return (lp_do_parameter(bInGlobalSection ? -2 : iServiceIndex,
2412                                 pszParmName, pszParmValue));
2413 }
2414
2415 /*
2416   variable argument do parameter
2417 */
2418 static BOOL do_parameter_var(const char *pszParmName, const char *fmt, ...) PRINTF_ATTRIBUTE(2, 3);
2419
2420 static BOOL do_parameter_var(const char *pszParmName, const char *fmt, ...)
2421 {
2422         char *s;
2423         BOOL ret;
2424         va_list ap;
2425
2426         va_start(ap, fmt);      
2427         s = talloc_vasprintf(NULL, fmt, ap);
2428         va_end(ap);
2429         ret = do_parameter(pszParmName, s);
2430         talloc_free(s);
2431         return ret;
2432 }
2433
2434
2435 /*
2436   set a parameter from the commandline - this is called from command line parameter
2437   parsing code. It sets the parameter then marks the parameter as unable to be modified
2438   by smb.conf processing
2439 */
2440 BOOL lp_set_cmdline(const char *pszParmName, const char *pszParmValue)
2441 {
2442         int parmnum = map_parameter(pszParmName);
2443         int i;
2444
2445         while (isspace(*pszParmValue)) pszParmValue++;
2446
2447
2448         if (parmnum < 0 && strchr(pszParmName, ':')) {
2449                 /* set a parametric option */
2450                 return lp_do_parameter_parametric(-1, pszParmName, pszParmValue, FLAG_CMDLINE);
2451         }
2452
2453         if (parmnum < 0) {
2454                 DEBUG(0,("Unknown option '%s'\n", pszParmName));
2455                 return False;
2456         }
2457
2458         /* reset the CMDLINE flag in case this has been called before */
2459         parm_table[parmnum].flags &= ~FLAG_CMDLINE;
2460
2461         if (!lp_do_parameter(-2, pszParmName, pszParmValue)) {
2462                 return False;
2463         }
2464
2465         parm_table[parmnum].flags |= FLAG_CMDLINE;
2466
2467         /* we have to also set FLAG_CMDLINE on aliases */
2468         for (i=parmnum-1;i>=0 && parm_table[i].ptr == parm_table[parmnum].ptr;i--) {
2469                 parm_table[i].flags |= FLAG_CMDLINE;
2470         }
2471         for (i=parmnum+1;i<NUMPARAMETERS && parm_table[i].ptr == parm_table[parmnum].ptr;i++) {
2472                 parm_table[i].flags |= FLAG_CMDLINE;
2473         }
2474
2475         return True;
2476 }
2477
2478 /*
2479   set a option from the commandline in 'a=b' format. Use to support --option
2480 */
2481 BOOL lp_set_option(const char *option)
2482 {
2483         char *p, *s;
2484         BOOL ret;
2485
2486         s = strdup(option);
2487         if (!s) {
2488                 return False;
2489         }
2490
2491         p = strchr(s, '=');
2492         if (!p) {
2493                 free(s);
2494                 return False;
2495         }
2496
2497         *p = 0;
2498
2499         ret = lp_set_cmdline(s, p+1);
2500         free(s);
2501         return ret;
2502 }
2503
2504
2505 #define BOOLSTR(b) ((b) ? "Yes" : "No")
2506
2507 /***************************************************************************
2508  Print a parameter of the specified type.
2509 ***************************************************************************/
2510
2511 static void print_parameter(struct parm_struct *p, void *ptr, FILE * f)
2512 {
2513         int i;
2514         switch (p->type)
2515         {
2516                 case P_ENUM:
2517                         for (i = 0; p->enum_list[i].name; i++) {
2518                                 if (*(int *)ptr == p->enum_list[i].value) {
2519                                         fprintf(f, "%s",
2520                                                 p->enum_list[i].name);
2521                                         break;
2522                                 }
2523                         }
2524                         break;
2525
2526                 case P_BOOL:
2527                         fprintf(f, "%s", BOOLSTR(*(BOOL *)ptr));
2528                         break;
2529
2530                 case P_INTEGER:
2531                         fprintf(f, "%d", *(int *)ptr);
2532                         break;
2533
2534                 case P_LIST:
2535                         if ((char ***)ptr && *(char ***)ptr) {
2536                                 char **list = *(char ***)ptr;
2537                                 
2538                                 for (; *list; list++)
2539                                         fprintf(f, "%s%s", *list,
2540                                                 ((*(list+1))?", ":""));
2541                         }
2542                         break;
2543
2544                 case P_STRING:
2545                 case P_USTRING:
2546                         if (*(char **)ptr) {
2547                                 fprintf(f, "%s", *(char **)ptr);
2548                         }
2549                         break;
2550                 case P_SEP:
2551                         break;
2552         }
2553 }
2554
2555 /***************************************************************************
2556  Check if two parameters are equal.
2557 ***************************************************************************/
2558
2559 static BOOL equal_parameter(parm_type type, void *ptr1, void *ptr2)
2560 {
2561         switch (type) {
2562                 case P_BOOL:
2563                         return (*((BOOL *)ptr1) == *((BOOL *)ptr2));
2564
2565                 case P_INTEGER:
2566                 case P_ENUM:
2567                         return (*((int *)ptr1) == *((int *)ptr2));
2568
2569                 case P_LIST:
2570                         return str_list_equal((const char **)(*(char ***)ptr1), 
2571                                               (const char **)(*(char ***)ptr2));
2572
2573                 case P_STRING:
2574                 case P_USTRING:
2575                 {
2576                         char *p1 = *(char **)ptr1, *p2 = *(char **)ptr2;
2577                         if (p1 && !*p1)
2578                                 p1 = NULL;
2579                         if (p2 && !*p2)
2580                                 p2 = NULL;
2581                         return (p1 == p2 || strequal(p1, p2));
2582                 }
2583                 case P_SEP:
2584                         break;
2585         }
2586         return (False);
2587 }
2588
2589 /***************************************************************************
2590  Process a new section (service). At this stage all sections are services.
2591  Later we'll have special sections that permit server parameters to be set.
2592  Returns True on success, False on failure. 
2593 ***************************************************************************/
2594
2595 static BOOL do_section(const char *pszSectionName)
2596 {
2597         BOOL bRetval;
2598         BOOL isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
2599                          (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
2600         bRetval = False;
2601
2602         /* if we've just struck a global section, note the fact. */
2603         bInGlobalSection = isglobal;
2604
2605         /* check for multiple global sections */
2606         if (bInGlobalSection) {
2607                 DEBUG(3, ("Processing section \"[%s]\"\n", pszSectionName));
2608                 return (True);
2609         }
2610
2611         if (!bInGlobalSection && bGlobalOnly)
2612                 return (True);
2613
2614         /* if we have a current service, tidy it up before moving on */
2615         bRetval = True;
2616
2617         if (iServiceIndex >= 0)
2618                 bRetval = service_ok(iServiceIndex);
2619
2620         /* if all is still well, move to the next record in the services array */
2621         if (bRetval) {
2622                 /* We put this here to avoid an odd message order if messages are */
2623                 /* issued by the post-processing of a previous section. */
2624                 DEBUG(2, ("Processing section \"[%s]\"\n", pszSectionName));
2625
2626                 if ((iServiceIndex = add_a_service(&sDefault, pszSectionName))
2627                     < 0) {
2628                         DEBUG(0, ("Failed to add a new service\n"));
2629                         return (False);
2630                 }
2631         }
2632
2633         return (bRetval);
2634 }
2635
2636
2637 /***************************************************************************
2638  Determine if a partcular base parameter is currentl set to the default value.
2639 ***************************************************************************/
2640
2641 static BOOL is_default(int i)
2642 {
2643         if (!defaults_saved)
2644                 return False;
2645         switch (parm_table[i].type) {
2646                 case P_LIST:
2647                         return str_list_equal((const char **)parm_table[i].def.lvalue, 
2648                                               (const char **)(*(char ***)parm_table[i].ptr));
2649                 case P_STRING:
2650                 case P_USTRING:
2651                         return strequal(parm_table[i].def.svalue,
2652                                         *(char **)parm_table[i].ptr);
2653                 case P_BOOL:
2654                         return parm_table[i].def.bvalue ==
2655                                 *(BOOL *)parm_table[i].ptr;
2656                 case P_INTEGER:
2657                 case P_ENUM:
2658                         return parm_table[i].def.ivalue ==
2659                                 *(int *)parm_table[i].ptr;
2660                 case P_SEP:
2661                         break;
2662         }
2663         return False;
2664 }
2665
2666 /***************************************************************************
2667 Display the contents of the global structure.
2668 ***************************************************************************/
2669
2670 static void dump_globals(FILE *f)
2671 {
2672         int i;
2673         struct param_opt *data;
2674         
2675         fprintf(f, "# Global parameters\n[global]\n");
2676
2677         for (i = 0; parm_table[i].label; i++)
2678                 if (parm_table[i].class == P_GLOBAL &&
2679                     parm_table[i].ptr &&
2680                     (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) {
2681                         if (defaults_saved && is_default(i))
2682                                 continue;
2683                         fprintf(f, "\t%s = ", parm_table[i].label);
2684                         print_parameter(&parm_table[i], parm_table[i].ptr, f);
2685                         fprintf(f, "\n");
2686         }
2687         if (Globals.param_opt != NULL) {
2688                 data = Globals.param_opt;
2689                 while(data) {
2690                         fprintf(f, "\t%s = %s\n", data->key, data->value);
2691                         data = data->next;
2692                 }
2693         }
2694
2695 }
2696
2697 /***************************************************************************
2698  Display the contents of a single services record.
2699 ***************************************************************************/
2700
2701 static void dump_a_service(service * pService, FILE * f)
2702 {
2703         int i;
2704         struct param_opt *data;
2705         
2706         if (pService != &sDefault)
2707                 fprintf(f, "\n[%s]\n", pService->szService);
2708
2709         for (i = 0; parm_table[i].label; i++)
2710                 if (parm_table[i].class == P_LOCAL &&
2711                     parm_table[i].ptr &&
2712                     (*parm_table[i].label != '-') &&
2713                     (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) {
2714                         int pdiff = PTR_DIFF(parm_table[i].ptr, &sDefault);
2715
2716                         if (pService == &sDefault) {
2717                                 if (defaults_saved && is_default(i))
2718                                         continue;
2719                         } else {
2720                                 if (equal_parameter(parm_table[i].type,
2721                                                     ((char *)pService) +
2722                                                     pdiff,
2723                                                     ((char *)&sDefault) +
2724                                                     pdiff))
2725                                         continue;
2726                         }
2727
2728                         fprintf(f, "\t%s = ", parm_table[i].label);
2729                         print_parameter(&parm_table[i],
2730                                         ((char *)pService) + pdiff, f);
2731                         fprintf(f, "\n");
2732         }
2733         if (pService->param_opt != NULL) {
2734                 data = pService->param_opt;
2735                 while(data) {
2736                         fprintf(f, "\t%s = %s\n", data->key, data->value);
2737                         data = data->next;
2738                 }
2739         }
2740 }
2741
2742
2743 /***************************************************************************
2744  Return info about the next service  in a service. snum==-1 gives the globals.
2745  Return NULL when out of parameters.
2746 ***************************************************************************/
2747
2748 struct parm_struct *lp_next_parameter(int snum, int *i, int allparameters)
2749 {
2750         if (snum == -1) {
2751                 /* do the globals */
2752                 for (; parm_table[*i].label; (*i)++) {
2753                         if (parm_table[*i].class == P_SEPARATOR)
2754                                 return &parm_table[(*i)++];
2755
2756                         if (!parm_table[*i].ptr
2757                             || (*parm_table[*i].label == '-'))
2758                                 continue;
2759
2760                         if ((*i) > 0
2761                             && (parm_table[*i].ptr ==
2762                                 parm_table[(*i) - 1].ptr))
2763                                 continue;
2764
2765                         return &parm_table[(*i)++];
2766                 }
2767         } else {
2768                 service *pService = ServicePtrs[snum];
2769
2770                 for (; parm_table[*i].label; (*i)++) {
2771                         if (parm_table[*i].class == P_SEPARATOR)
2772                                 return &parm_table[(*i)++];
2773
2774                         if (parm_table[*i].class == P_LOCAL &&
2775                             parm_table[*i].ptr &&
2776                             (*parm_table[*i].label != '-') &&
2777                             ((*i) == 0 ||
2778                              (parm_table[*i].ptr !=
2779                               parm_table[(*i) - 1].ptr)))
2780                         {
2781                                 int pdiff =
2782                                         PTR_DIFF(parm_table[*i].ptr,
2783                                                  &sDefault);
2784
2785                                 if (allparameters ||
2786                                     !equal_parameter(parm_table[*i].type,
2787                                                      ((char *)pService) +
2788                                                      pdiff,
2789                                                      ((char *)&sDefault) +
2790                                                      pdiff))
2791                                 {
2792                                         return &parm_table[(*i)++];
2793                                 }
2794                         }
2795                 }
2796         }
2797
2798         return NULL;
2799 }
2800
2801
2802 /***************************************************************************
2803  Return TRUE if the passed service number is within range.
2804 ***************************************************************************/
2805
2806 BOOL lp_snum_ok(int iService)
2807 {
2808         return (LP_SNUM_OK(iService) && ServicePtrs[iService]->bAvailable);
2809 }
2810
2811 /***************************************************************************
2812  Auto-load some home services.
2813 ***************************************************************************/
2814
2815 static void lp_add_auto_services(const char *str)
2816 {
2817         return;
2818 }
2819
2820 /***************************************************************************
2821  Auto-load one printer.
2822 ***************************************************************************/
2823
2824 void lp_add_one_printer(char *name, char *comment)
2825 {
2826         int printers = lp_servicenumber(PRINTERS_NAME);
2827         int i;
2828
2829         if (lp_servicenumber(name) < 0) {
2830                 lp_add_printer(name, printers);
2831                 if ((i = lp_servicenumber(name)) >= 0) {
2832                         string_set(&ServicePtrs[i]->comment, comment);
2833                         ServicePtrs[i]->autoloaded = True;
2834                 }
2835         }
2836 }
2837
2838 /***************************************************************************
2839  Announce ourselves as a print server.
2840 ***************************************************************************/
2841
2842 void update_server_announce_as_printserver(void)
2843 {
2844         default_server_announce |= SV_TYPE_PRINTQ_SERVER;       
2845 }
2846
2847 /***************************************************************************
2848  Have we loaded a services file yet?
2849 ***************************************************************************/
2850
2851 BOOL lp_loaded(void)
2852 {
2853         return (bLoaded);
2854 }
2855
2856 /***************************************************************************
2857  Unload unused services.
2858 ***************************************************************************/
2859
2860 void lp_killunused(struct smbsrv_connection *smb, BOOL (*snumused) (struct smbsrv_connection *, int))
2861 {
2862         int i;
2863         for (i = 0; i < iNumServices; i++) {
2864                 if (!VALID(i))
2865                         continue;
2866
2867                 if (!snumused || !snumused(smb, i)) {
2868                         ServicePtrs[i]->valid = False;
2869                         free_service(ServicePtrs[i]);
2870                 }
2871         }
2872 }
2873
2874 /***************************************************************************
2875  Unload a service.
2876 ***************************************************************************/
2877
2878 void lp_killservice(int iServiceIn)
2879 {
2880         if (VALID(iServiceIn)) {
2881                 ServicePtrs[iServiceIn]->valid = False;
2882                 free_service(ServicePtrs[iServiceIn]);
2883         }
2884 }
2885
2886 /***************************************************************************
2887  Save the curent values of all global and sDefault parameters into the 
2888  defaults union. This allows swat and testparm to show only the
2889  changed (ie. non-default) parameters.
2890 ***************************************************************************/
2891
2892 static void lp_save_defaults(void)
2893 {
2894         int i;
2895         for (i = 0; parm_table[i].label; i++) {
2896                 if (i > 0 && parm_table[i].ptr == parm_table[i - 1].ptr)
2897                         continue;
2898                 switch (parm_table[i].type) {
2899                         case P_LIST:
2900                                 parm_table[i].def.lvalue = str_list_copy(talloc_autofree_context(), 
2901                                                                          *(const char ***)parm_table[i].ptr);
2902                                 break;
2903                         case P_STRING:
2904                         case P_USTRING:
2905                                 if (parm_table[i].ptr) {
2906                                         parm_table[i].def.svalue = strdup(*(char **)parm_table[i].ptr);
2907                                 } else {
2908                                         parm_table[i].def.svalue = NULL;
2909                                 }
2910                                 break;
2911                         case P_BOOL:
2912                                 parm_table[i].def.bvalue =
2913                                         *(BOOL *)parm_table[i].ptr;
2914                                 break;
2915                         case P_INTEGER:
2916                         case P_ENUM:
2917                                 parm_table[i].def.ivalue =
2918                                         *(int *)parm_table[i].ptr;
2919                                 break;
2920                         case P_SEP:
2921                                 break;
2922                 }
2923         }
2924         defaults_saved = True;
2925 }
2926
2927 /*******************************************************************
2928  Set the server type we will announce as via nmbd.
2929 ********************************************************************/
2930
2931 static void set_server_role(void)
2932 {
2933         server_role = ROLE_STANDALONE;
2934
2935         switch (lp_security()) {
2936                 case SEC_SHARE:
2937                         if (lp_domain_logons())
2938                                 DEBUG(0, ("Server's Role (logon server) conflicts with share-level security\n"));
2939                         break;
2940                 case SEC_SERVER:
2941                 case SEC_DOMAIN:
2942                 case SEC_ADS:
2943                         if (lp_domain_logons()) {
2944                                 if (Globals.bDomainMaster) /* auto or yes */ 
2945                                         server_role = ROLE_DOMAIN_PDC;
2946                                 else
2947                                         server_role = ROLE_DOMAIN_BDC;
2948                                 break;
2949                         }
2950                         server_role = ROLE_DOMAIN_MEMBER;
2951                         break;
2952                 case SEC_USER:
2953                         if (lp_domain_logons()) {
2954
2955                                 if (Globals.bDomainMaster) /* auto or yes */ 
2956                                         server_role = ROLE_DOMAIN_PDC;
2957                                 else
2958                                         server_role = ROLE_DOMAIN_BDC;
2959                         }
2960                         break;
2961                 default:
2962                         DEBUG(0, ("Server's Role undefined due to unknown security mode\n"));
2963                         break;
2964         }
2965
2966         DEBUG(10, ("set_server_role: role = "));
2967
2968         switch(server_role) {
2969         case ROLE_STANDALONE:
2970                 DEBUGADD(10, ("ROLE_STANDALONE\n"));
2971                 break;
2972         case ROLE_DOMAIN_MEMBER:
2973                 DEBUGADD(10, ("ROLE_DOMAIN_MEMBER\n"));
2974                 break;
2975         case ROLE_DOMAIN_BDC:
2976                 DEBUGADD(10, ("ROLE_DOMAIN_BDC\n"));
2977                 break;
2978         case ROLE_DOMAIN_PDC:
2979                 DEBUGADD(10, ("ROLE_DOMAIN_PDC\n"));
2980                 break;
2981         }
2982 }
2983
2984 /***************************************************************************
2985  Load the services array from the services file. Return True on success, 
2986  False on failure.
2987 ***************************************************************************/
2988
2989 BOOL lp_load(const char *pszFname, BOOL global_only, BOOL save_defaults,
2990              BOOL add_ipc)
2991 {
2992         pstring n2;
2993         BOOL bRetval;
2994         struct param_opt *data;
2995
2996         pstrcpy(n2, pszFname);
2997         standard_sub_basic(n2,sizeof(n2));
2998
2999         add_to_file_list(pszFname, n2);
3000
3001         bRetval = False;
3002
3003         DEBUG(2, ("lp_load: refreshing parameters from %s\n", pszFname));
3004         
3005         bInGlobalSection = True;
3006         bGlobalOnly = global_only;
3007
3008         if (Globals.param_opt != NULL) {
3009                 struct param_opt *next;
3010                 for (data=Globals.param_opt; data; data=next) {
3011                         next = data->next;
3012                         if (data->flags & FLAG_CMDLINE) continue;
3013                         free(data->key);
3014                         free(data->value);
3015                         DLIST_REMOVE(Globals.param_opt, data);
3016                         free(data);
3017                 }
3018         }
3019         
3020         init_globals();
3021
3022         if (save_defaults)
3023         {
3024                 lp_save_defaults();
3025         }
3026
3027         /* We get sections first, so have to start 'behind' to make up */
3028         iServiceIndex = -1;
3029         bRetval = pm_process(n2, do_section, do_parameter);
3030
3031         /* finish up the last section */
3032         DEBUG(4, ("pm_process() returned %s\n", BOOLSTR(bRetval)));
3033         if (bRetval)
3034                 if (iServiceIndex >= 0)
3035                         bRetval = service_ok(iServiceIndex);
3036
3037         lp_add_auto_services(lp_auto_services());
3038
3039         if (add_ipc) {
3040                 /* When 'restrict anonymous = 2' guest connections to ipc$
3041                    are denied */
3042                 lp_add_hidden("IPC$", "IPC", (lp_restrict_anonymous() < 2));
3043                 lp_add_hidden("ADMIN$", "DISK", False);
3044         }
3045
3046         set_server_role();
3047         set_default_server_announce_type();
3048
3049         bLoaded = True;
3050
3051         /* Now we check bWINSsupport and set szWINSserver to 127.0.0.1 */
3052         /* if bWINSsupport is true and we are in the client            */
3053         if (in_client && Globals.bWINSsupport) {
3054                 lp_do_parameter(-1, "wins server", "127.0.0.1");
3055         }
3056
3057         init_iconv();
3058
3059         return (bRetval);
3060 }
3061
3062 /***************************************************************************
3063  Reset the max number of services.
3064 ***************************************************************************/
3065
3066 void lp_resetnumservices(void)
3067 {
3068         iNumServices = 0;
3069 }
3070
3071 /***************************************************************************
3072  Return the max number of services.
3073 ***************************************************************************/
3074
3075 int lp_numservices(void)
3076 {
3077         return (iNumServices);
3078 }
3079
3080 /***************************************************************************
3081 Display the contents of the services array in human-readable form.
3082 ***************************************************************************/
3083
3084 void lp_dump(FILE *f, BOOL show_defaults, int maxtoprint)
3085 {
3086         int iService;
3087
3088         if (show_defaults)
3089                 defaults_saved = False;
3090
3091         dump_globals(f);
3092
3093         dump_a_service(&sDefault, f);
3094
3095         for (iService = 0; iService < maxtoprint; iService++)
3096                 lp_dump_one(f, show_defaults, iService);
3097 }
3098
3099 /***************************************************************************
3100 Display the contents of one service in human-readable form.
3101 ***************************************************************************/
3102
3103 void lp_dump_one(FILE * f, BOOL show_defaults, int snum)
3104 {
3105         if (VALID(snum)) {
3106                 if (ServicePtrs[snum]->szService[0] == '\0')
3107                         return;
3108                 dump_a_service(ServicePtrs[snum], f);
3109         }
3110 }
3111
3112 /***************************************************************************
3113 Return the number of the service with the given name, or -1 if it doesn't
3114 exist. Note that this is a DIFFERENT ANIMAL from the internal function
3115 getservicebyname()! This works ONLY if all services have been loaded, and
3116 does not copy the found service.
3117 ***************************************************************************/
3118
3119 int lp_servicenumber(const char *pszServiceName)
3120 {
3121         int iService;
3122         fstring serviceName;
3123  
3124  
3125         for (iService = iNumServices - 1; iService >= 0; iService--) {
3126                 if (VALID(iService) && ServicePtrs[iService]->szService) {
3127                         /*
3128                          * The substitution here is used to support %U is
3129                          * service names
3130                          */
3131                         fstrcpy(serviceName, ServicePtrs[iService]->szService);
3132                         standard_sub_basic(serviceName,sizeof(serviceName));
3133                         if (strequal(serviceName, pszServiceName))
3134                                 break;
3135                 }
3136         }
3137
3138         if (iService < 0)
3139                 DEBUG(7,("lp_servicenumber: couldn't find %s\n", pszServiceName));
3140
3141         return (iService);
3142 }
3143
3144 /*******************************************************************
3145  A useful volume label function. 
3146 ********************************************************************/
3147 const char *volume_label(int snum)
3148 {
3149         const char *ret = lp_volume(snum);
3150         if (!*ret)
3151                 return lp_servicename(snum);
3152         return (ret);
3153 }
3154
3155
3156 /*******************************************************************
3157  Set the server type we will announce as via nmbd.
3158 ********************************************************************/
3159
3160 static void set_default_server_announce_type(void)
3161 {
3162         default_server_announce = 0;
3163         default_server_announce |= SV_TYPE_WORKSTATION;
3164         default_server_announce |= SV_TYPE_SERVER;
3165         default_server_announce |= SV_TYPE_SERVER_UNIX;
3166
3167         switch (lp_announce_as()) {
3168                 case ANNOUNCE_AS_NT_SERVER:
3169                         default_server_announce |= SV_TYPE_SERVER_NT;
3170                         /* fall through... */
3171                 case ANNOUNCE_AS_NT_WORKSTATION:
3172                         default_server_announce |= SV_TYPE_NT;
3173                         break;
3174                 case ANNOUNCE_AS_WIN95:
3175                         default_server_announce |= SV_TYPE_WIN95_PLUS;
3176                         break;
3177                 case ANNOUNCE_AS_WFW:
3178                         default_server_announce |= SV_TYPE_WFW;
3179                         break;
3180                 default:
3181                         break;
3182         }
3183
3184         switch (lp_server_role()) {
3185                 case ROLE_DOMAIN_MEMBER:
3186                         default_server_announce |= SV_TYPE_DOMAIN_MEMBER;
3187                         break;
3188                 case ROLE_DOMAIN_PDC:
3189                         default_server_announce |= SV_TYPE_DOMAIN_CTRL;
3190                         break;
3191                 case ROLE_DOMAIN_BDC:
3192                         default_server_announce |= SV_TYPE_DOMAIN_BAKCTRL;
3193                         break;
3194                 case ROLE_STANDALONE:
3195                 default:
3196                         break;
3197         }
3198         if (lp_time_server())
3199                 default_server_announce |= SV_TYPE_TIME_SOURCE;
3200
3201         if (lp_host_msdfs())
3202                 default_server_announce |= SV_TYPE_DFS_SERVER;
3203
3204         /* TODO: only announce us as print server when we are a print server */
3205         default_server_announce |= SV_TYPE_PRINTQ_SERVER;
3206 }
3207
3208 /***********************************************************
3209  returns role of Samba server
3210 ************************************************************/
3211
3212 int lp_server_role(void)
3213 {
3214         return server_role;
3215 }
3216
3217 /***********************************************************
3218  If we are PDC then prefer us as DMB
3219 ************************************************************/
3220
3221 BOOL lp_domain_master(void)
3222 {
3223         if (Globals.bDomainMaster == Auto)
3224                 return (lp_server_role() == ROLE_DOMAIN_PDC);
3225
3226         return Globals.bDomainMaster;
3227 }
3228
3229 /***********************************************************
3230  If we are DMB then prefer us as LMB
3231 ************************************************************/
3232
3233 BOOL lp_preferred_master(void)
3234 {
3235         if (Globals.bPreferredMaster == Auto)
3236                 return (lp_local_master() && lp_domain_master());
3237
3238         return Globals.bPreferredMaster;
3239 }
3240
3241 /*******************************************************************
3242  Remove a service.
3243 ********************************************************************/
3244
3245 void lp_remove_service(int snum)
3246 {
3247         ServicePtrs[snum]->valid = False;
3248 }
3249
3250 /*******************************************************************
3251  Copy a service.
3252 ********************************************************************/
3253
3254 void lp_copy_service(int snum, const char *new_name)
3255 {
3256         const char *oldname = lp_servicename(snum);
3257         do_section(new_name);
3258         if (snum >= 0) {
3259                 snum = lp_servicenumber(new_name);
3260                 if (snum >= 0)
3261                         lp_do_parameter(snum, "copy", oldname);
3262         }
3263 }
3264
3265
3266 /*******************************************************************
3267  Get the default server type we will announce as via nmbd.
3268 ********************************************************************/
3269 int lp_default_server_announce(void)
3270 {
3271         return default_server_announce;
3272 }
3273
3274 const char *lp_printername(int snum)
3275 {
3276         const char *ret = _lp_printername(snum);
3277         if (ret == NULL || (ret != NULL && *ret == '\0'))
3278                 ret = lp_const_servicename(snum);
3279
3280         return ret;
3281 }
3282
3283
3284 /*******************************************************************
3285  Return the max print jobs per queue.
3286 ********************************************************************/
3287
3288 int lp_maxprintjobs(int snum)
3289 {
3290         int maxjobs = LP_SNUM_OK(snum) ? ServicePtrs[snum]->iMaxPrintJobs : sDefault.iMaxPrintJobs;
3291         if (maxjobs <= 0 || maxjobs >= PRINT_MAX_JOBID)
3292                 maxjobs = PRINT_MAX_JOBID - 1;
3293
3294         return maxjobs;
3295 }