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