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