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