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