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