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