rpc_parse/parse_misc.c : defined a new BUFFER5 struct
[ira/wip.git] / source3 / param / loadparm.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    Parameter loading functions
5    Copyright (C) Karl Auer 1993-1998
6
7    Largely re-written by Andrew Tridgell, September 1994
8    
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 2 of the License, or
12    (at your option) any later version.
13    
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18    
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23
24 /*
25  *  Load parameters.
26  *
27  *  This module provides suitable callback functions for the params
28  *  module. It builds the internal table of service details which is
29  *  then used by the rest of the server.
30  *
31  * To add a parameter:
32  *
33  * 1) add it to the global or service structure definition
34  * 2) add it to the parm_table
35  * 3) add it to the list of available functions (eg: using FN_GLOBAL_STRING())
36  * 4) If it's a global then initialise it in init_globals. If a local
37  *    (ie. service) parameter then initialise it in the sDefault structure
38  *  
39  *
40  * Notes:
41  *   The configuration file is processed sequentially for speed. It is NOT
42  *   accessed randomly as happens in 'real' Windows. For this reason, there
43  *   is a fair bit of sequence-dependent code here - ie., code which assumes
44  *   that certain things happen before others. In particular, the code which
45  *   happens at the boundary between sections is delicately poised, so be
46  *   careful!
47  *
48  */
49
50 #include "includes.h"
51
52 /* Set default coding system for KANJI if none specified in Makefile. */
53 /* 
54  * We treat KANJI specially due to historical precedent (it was the
55  * first non-english codepage added to Samba). With the new dynamic
56  * codepage support this is not needed anymore.
57  *
58  * The define 'KANJI' is being overloaded to mean 'use kanji codepage
59  * by default' and also 'this is the filename-to-disk conversion 
60  * method to use'. This really should be removed and all control
61  * over this left in the smb.conf parameters 'client codepage'
62  * and 'coding system'.
63  */
64 #ifndef KANJI
65 #define KANJI "sbcs"
66 #endif /* KANJI */
67
68 BOOL in_client = False;   /* Not in the client by default */
69 BOOL bLoaded = False;
70
71 extern int DEBUGLEVEL;
72 extern pstring user_socket_options;
73 extern pstring global_myname;
74
75 #ifndef GLOBAL_NAME
76 #define GLOBAL_NAME "global"
77 #endif
78
79 #ifndef PRINTERS_NAME
80 #define PRINTERS_NAME "printers"
81 #endif
82
83 #ifndef HOMES_NAME
84 #define HOMES_NAME "homes"
85 #endif
86
87 /* some helpful bits */
88 #define pSERVICE(i) ServicePtrs[i]
89 #define iSERVICE(i) (*pSERVICE(i))
90 #define LP_SNUM_OK(iService) (((iService) >= 0) && ((iService) < iNumServices) && iSERVICE(iService).valid)
91 #define VALID(i) iSERVICE(i).valid
92
93 int keepalive=DEFAULT_KEEPALIVE;
94 extern BOOL use_getwd_cache;
95
96 extern int extra_time_offset;
97
98 static BOOL defaults_saved=False;
99
100 /* 
101  * This structure describes global (ie., server-wide) parameters.
102  */
103 typedef struct
104 {
105   char *szPrintcapname;
106   char *szLockDir;
107   char *szRootdir;
108   char *szDefaultService;
109   char *szDfree;
110   char *szMsgCommand;
111   char *szHostsEquiv;
112   char *szServerString;
113   char *szAutoServices;
114   char *szPasswdProgram;
115   char *szPasswdChat;
116   char *szLogFile;
117   char *szConfigFile;
118   char *szSMBPasswdFile;
119   char *szSMBPassGroupFile;
120   char *szSMBGroupFile;
121   char *szSMBAliasFile;
122   char *szPasswordServer;
123   char *szSocketOptions;
124   char *szValidChars;
125   char *szWorkGroup;
126   char *szUsernameMap;
127   char *szAliasnameMap;
128   char *szGroupnameMap;
129   char *szBuiltinnameMap;
130   char *szNTusernameMap;
131   char *szCharacterSet;
132   char *szLogonScript;
133   char *szLogonPath;
134   char *szLogonDrive;
135   char *szLogonHome;
136   char *szSmbrun;
137   char *szWINSserver;
138   char *szCodingSystem;
139   char *szInterfaces;
140   char *szRemoteAnnounce;
141   char *szRemoteBrowseSync;
142   char *szSocketAddress;
143   char *szNISHomeMapName;
144   char *szAnnounceVersion; /* This is initialised in init_globals */
145   char *szNetbiosAliases;
146   char *szDomainOtherSIDs;
147   char *szDriverFile;
148   char *szNameResolveOrder;
149 #ifdef WITH_LDAP
150   char *szLdapServer;
151   char *szLdapSuffix;
152   char *szLdapBindAs;
153   char *szLdapPasswdFile; 
154 #endif /* WITH_LDAP */
155   char *szPanicAction;
156   char *szNtForms;
157   char *szNtDriverFile;  
158   int max_log_size;
159   int mangled_stack;
160   int max_xmit;
161   int max_mux;
162   int max_open_files;
163   int max_packet;
164   int pwordlevel;
165   int unamelevel;
166   int deadtime;
167   int maxprotocol;
168   int security;
169   int maxdisksize;
170   int lpqcachetime;
171   int syslog;
172   int os_level;
173   int max_ttl;
174   int max_wins_ttl;
175   int min_wins_ttl;
176   int ReadSize;
177   int lm_announce;
178   int lm_interval;
179   int shmem_size;
180   int client_code_page;
181   int announce_as;   /* This is initialised in init_globals */
182   int machine_password_timeout;
183   int change_notify_timeout;
184   int stat_cache_size;
185   int map_to_guest;
186 #ifdef WITH_LDAP
187   int ldap_port;
188 #endif /* WITH_LDAP */
189 #ifdef WITH_SSL
190   int sslVersion;
191   char *sslHostsRequire;
192   char *sslHostsResign;
193   char *sslCaCertDir;
194   char *sslCaCertFile;
195   char *sslCert;
196   char *sslPrivKey;
197   char *sslClientCert;
198   char *sslClientPrivKey;
199   char *sslCiphers;
200   BOOL sslEnabled;
201   BOOL sslReqClientCert;
202   BOOL sslReqServerCert;
203   BOOL sslCompatibility;
204 #endif /* WITH_SSL */
205   BOOL bDNSproxy;
206   BOOL bWINSsupport;
207   BOOL bWINSproxy;
208   BOOL bLocalMaster;
209   BOOL bPreferredMaster;
210   BOOL bDomainMaster;
211   BOOL bDomainLogons;
212   BOOL bEncryptPasswords;
213   BOOL bUpdateEncrypt;
214   BOOL bStripDot;
215   BOOL bNullPasswords;
216   BOOL bLoadPrinters;
217   BOOL bUseRhosts;
218   BOOL bReadRaw;
219   BOOL bWriteRaw;
220   BOOL bReadPrediction;
221   BOOL bReadbmpx;
222   BOOL bSyslogOnly;
223   BOOL bBrowseList;
224   BOOL bUnixRealname;
225   BOOL bNISHomeMap;
226   BOOL bTimeServer;
227   BOOL bBindInterfacesOnly;
228   BOOL bUnixPasswdSync;
229   BOOL bPasswdChatDebug;
230   BOOL bOleLockingCompat;
231   BOOL bTimestampLogs;
232   BOOL bNTSmbSupport;
233   BOOL bNTPipeSupport;
234   BOOL bStatCache;
235   BOOL bKernelOplocks;
236 #if defined(HAVE_MYSQL_H) && defined(WITH_MYSQLSAM)
237   char *sMysqlDatabase;
238   char *sMysqlTable;
239   char *sMysqlUser;
240   char *sMysqlHost;
241   char *sMysqlPassFile;
242 #endif
243 } global;
244
245 static global Globals;
246
247
248
249 /* 
250  * This structure describes a single service. 
251  */
252 typedef struct
253 {
254   BOOL valid;
255   char *szService;
256   char *szPath;
257   char *szUsername;
258   char *szGuestaccount;
259   char *szInvalidUsers;
260   char *szValidUsers;
261   char *szAdminUsers;
262   char *szCopy;
263   char *szInclude;
264   char *szPreExec;
265   char *szPostExec;
266   char *szRootPreExec;
267   char *szRootPostExec;
268   char *szPrintcommand;
269   char *szLpqcommand;
270   char *szLprmcommand;
271   char *szLppausecommand;
272   char *szLpresumecommand;
273   char *szQueuepausecommand;
274   char *szQueueresumecommand;
275   char *szPrintername;
276   char *szPrinterDriver;
277   char *szPrinterDriverLocation;
278   char *szDontdescend;
279   char *szHostsallow;
280   char *szHostsdeny;
281   char *szMagicScript;
282   char *szMagicOutput;
283   char *szMangledMap;
284   char *szVetoFiles;
285   char *szHideFiles;
286   char *szVetoOplockFiles;
287   char *comment;
288   char *force_user;
289   char *force_group;
290   char *readlist;
291   char *writelist;
292   char *volume;
293   char *fstype;
294   char *vfsObjectFile;
295   int  iMinPrintSpace;
296   int  iCreate_mask;
297   int  iCreate_force_mode;
298   int  iDir_mask;
299   int  iDir_force_mode;
300   int  iMaxConnections;
301   int  iDefaultCase;
302   int  iPrinting;
303   BOOL bAlternatePerm;
304   BOOL bRevalidate;
305   BOOL bCaseSensitive;
306   BOOL bCasePreserve;
307   BOOL bShortCasePreserve;
308   BOOL bCaseMangle;
309   BOOL status;
310   BOOL bHideDotFiles;
311   BOOL bBrowseable;
312   BOOL bAvailable;
313   BOOL bRead_only;
314   BOOL bNo_set_dir;
315   BOOL bGuest_only;
316   BOOL bGuest_ok;
317   BOOL bPrint_ok;
318   BOOL bPostscript;
319   BOOL bMap_system;
320   BOOL bMap_hidden;
321   BOOL bMap_archive;
322   BOOL bLocking;
323   BOOL bStrictLocking;
324   BOOL bShareModes;
325   BOOL bOpLocks;
326   BOOL bOnlyUser;
327   BOOL bMangledNames;
328   BOOL bWidelinks;
329   BOOL bSymlinks;
330   BOOL bSyncAlways;
331   BOOL bStrictSync;
332   char magic_char;
333   BOOL *copymap;
334   BOOL bDeleteReadonly;
335   BOOL bFakeOplocks;
336   BOOL bDeleteVetoFiles;
337   BOOL bDosFiletimes;
338   BOOL bDosFiletimeResolution;
339   BOOL bFakeDirCreateTimes;
340   BOOL bBlockingLocks;
341   char dummy[3]; /* for alignment */
342 } service;
343
344
345 /* This is a default service used to prime a services structure */
346 static service sDefault = 
347 {
348   True,   /* valid */
349   NULL,    /* szService */
350   NULL,    /* szPath */
351   NULL,    /* szUsername */
352   NULL,    /* szGuestAccount  - this is set in init_globals() */
353   NULL,    /* szInvalidUsers */
354   NULL,    /* szValidUsers */
355   NULL,    /* szAdminUsers */
356   NULL,    /* szCopy */
357   NULL,    /* szInclude */
358   NULL,    /* szPreExec */
359   NULL,    /* szPostExec */
360   NULL,    /* szRootPreExec */
361   NULL,    /* szRootPostExec */
362   NULL,    /* szPrintcommand */
363   NULL,    /* szLpqcommand */
364   NULL,    /* szLprmcommand */
365   NULL,    /* szLppausecommand */
366   NULL,    /* szLpresumecommand */
367   NULL,    /* szQueuepausecommand */
368   NULL,    /* szQueueresumecommand */
369   NULL,    /* szPrintername */
370   NULL,    /* szPrinterDriver - this is set in init_globals() */
371   NULL,    /* szPrinterDriverLocation */
372   NULL,    /* szDontdescend */
373   NULL,    /* szHostsallow */
374   NULL,    /* szHostsdeny */
375   NULL,    /* szMagicScript */
376   NULL,    /* szMagicOutput */
377   NULL,    /* szMangledMap */
378   NULL,    /* szVetoFiles */
379   NULL,    /* szHideFiles */
380   NULL,    /* szVetoOplockFiles */
381   NULL,    /* comment */
382   NULL,    /* force user */
383   NULL,    /* force group */
384   NULL,    /* readlist */
385   NULL,    /* writelist */
386   NULL,    /* volume */
387   NULL,    /* fstype */
388   NULL,    /* vfs object */
389   0,       /* iMinPrintSpace */
390   0744,    /* iCreate_mask */
391   0000,    /* iCreate_force_mode */
392   0755,    /* iDir_mask */
393   0000,    /* iDir_force_mode */
394   0,       /* iMaxConnections */
395   CASE_LOWER, /* iDefaultCase */
396   DEFAULT_PRINTING, /* iPrinting */
397   False,   /* bAlternatePerm */
398   False,   /* revalidate */
399   False,   /* case sensitive */
400   True,   /* case preserve */
401   True,   /* short case preserve */
402   False,  /* case mangle */
403   True,  /* status */
404   True,  /* bHideDotFiles */
405   True,  /* bBrowseable */
406   True,  /* bAvailable */
407   True,  /* bRead_only */
408   True,  /* bNo_set_dir */
409   False, /* bGuest_only */
410   False, /* bGuest_ok */
411   False, /* bPrint_ok */
412   False, /* bPostscript */
413   False, /* bMap_system */
414   False, /* bMap_hidden */
415   True,  /* bMap_archive */
416   True,  /* bLocking */
417   False,  /* bStrictLocking */
418   True,  /* bShareModes */
419   True,  /* bOpLocks */
420   False, /* bOnlyUser */
421   True,  /* bMangledNames */
422   True,  /* bWidelinks */
423   True,  /* bSymlinks */
424   False, /* bSyncAlways */
425   False, /* bStrictSync */
426   '~',   /* magic char */
427   NULL,  /* copymap */
428   False, /* bDeleteReadonly */
429   False, /* bFakeOplocks */
430   False, /* bDeleteVetoFiles */
431   False, /* bDosFiletimes */
432   False, /* bDosFiletimeResolution */
433   False, /* bFakeDirCreateTimes */
434   True,  /* bBlockingLocks */
435   ""     /* dummy */
436 };
437
438
439
440 /* local variables */
441 static service **ServicePtrs = NULL;
442 static int iNumServices = 0;
443 static int iServiceIndex = 0;
444 static BOOL bInGlobalSection = True;
445 static BOOL bGlobalOnly = False;
446 static int server_role;
447 static int default_server_announce;
448
449 #define NUMPARAMETERS (sizeof(parm_table) / sizeof(struct parm_struct))
450
451 /* prototypes for the special type handlers */
452 static BOOL handle_valid_chars(char *pszParmValue, char **ptr);
453 static BOOL handle_include(char *pszParmValue, char **ptr);
454 static BOOL handle_copy(char *pszParmValue, char **ptr);
455 static BOOL handle_character_set(char *pszParmValue,char **ptr);
456 static BOOL handle_coding_system(char *pszParmValue,char **ptr);
457 static BOOL handle_vfs_object(char *pszParmValue, char **ptr);
458
459 static void set_server_role(void);
460 static void set_default_server_announce_type(void);
461
462 static struct enum_list enum_protocol[] = {{PROTOCOL_NT1, "NT1"}, {PROTOCOL_LANMAN2, "LANMAN2"}, 
463                                            {PROTOCOL_LANMAN1, "LANMAN1"}, {PROTOCOL_CORE,"CORE"}, 
464                                            {PROTOCOL_COREPLUS, "COREPLUS"}, 
465                                            {PROTOCOL_COREPLUS, "CORE+"}, {-1, NULL}};
466
467 static struct enum_list enum_security[] = {{SEC_SHARE, "SHARE"},  {SEC_USER, "USER"}, 
468                                            {SEC_SERVER, "SERVER"}, {SEC_DOMAIN, "DOMAIN"},
469                                            {-1, NULL}};
470
471 static struct enum_list enum_printing[] = {{PRINT_SYSV, "sysv"}, {PRINT_AIX, "aix"}, 
472                                            {PRINT_HPUX, "hpux"}, {PRINT_BSD, "bsd"},
473                                            {PRINT_QNX, "qnx"},   {PRINT_PLP, "plp"},
474                                            {PRINT_LPRNG, "lprng"}, {PRINT_SOFTQ, "softq"},
475                                            {-1, NULL}};
476
477 static struct enum_list enum_announce_as[] = {{ANNOUNCE_AS_NT, "NT"}, {ANNOUNCE_AS_WIN95, "win95"},
478                                               {ANNOUNCE_AS_WFW, "WfW"}, {-1, NULL}};
479
480 static struct enum_list enum_case[] = {{CASE_LOWER, "lower"}, {CASE_UPPER, "upper"}, {-1, NULL}};
481
482 static struct enum_list enum_bool_auto[] = {{True, "True"}, {False, "False"}, {True, "Yes"}, {False, "No"}, {Auto, "Auto"}, {-1, NULL}};
483
484 /* 
485    Do you want session setups at user level security with a invalid
486    password to be rejected or allowed in as guest? WinNT rejects them
487    but it can be a pain as it means "net view" needs to use a password
488
489    You have 3 choices in the setting of map_to_guest:
490
491    "Never" means session setups with an invalid password
492    are rejected. This is the default.
493
494    "Bad User" means session setups with an invalid password
495    are rejected, unless the username does not exist, in which case it
496    is treated as a guest login
497
498    "Bad Password" means session setups with an invalid password
499    are treated as a guest login
500
501    Note that map_to_guest only has an effect in user or server
502    level security.
503 */
504
505 static struct enum_list enum_map_to_guest[] = {{NEVER_MAP_TO_GUEST, "Never"}, {MAP_TO_GUEST_ON_BAD_USER, "Bad User"}, {MAP_TO_GUEST_ON_BAD_PASSWORD, "Bad Password"}, {-1, NULL}};
506
507 #ifdef WITH_SSL
508 static struct enum_list enum_ssl_version[] = {{SMB_SSL_V2, "ssl2"}, {SMB_SSL_V3, "ssl3"},
509   {SMB_SSL_V23, "ssl2or3"}, {SMB_SSL_TLS1, "tls1"}, {-1, NULL}};
510 #endif
511
512 /* note that we do not initialise the defaults union - it is not allowed in ANSI C */
513 static struct parm_struct parm_table[] =
514 {
515   {"Base Options", P_SEP, P_SEPARATOR},
516
517   {"comment",          P_STRING,  P_LOCAL,  &sDefault.comment,          NULL,   NULL,  FLAG_BASIC|FLAG_PRINT},
518   {"path",             P_STRING,  P_LOCAL,  &sDefault.szPath,           NULL,   NULL,  FLAG_BASIC|FLAG_PRINT},
519   {"directory",        P_STRING,  P_LOCAL,  &sDefault.szPath,           NULL,   NULL,  0},
520   {"workgroup",        P_USTRING, P_GLOBAL, &Globals.szWorkGroup,       NULL,   NULL,  FLAG_BASIC},
521   {"netbios name",     P_UGSTRING,P_GLOBAL, global_myname,                     NULL,   NULL,  FLAG_BASIC},
522   {"netbios aliases",  P_STRING,  P_GLOBAL, &Globals.szNetbiosAliases,  NULL,   NULL,  0},
523   {"server string",    P_STRING,  P_GLOBAL, &Globals.szServerString,    NULL,   NULL,  FLAG_BASIC},
524   {"interfaces",       P_STRING,  P_GLOBAL, &Globals.szInterfaces,      NULL,   NULL,  FLAG_BASIC},
525   {"bind interfaces only", P_BOOL,P_GLOBAL, &Globals.bBindInterfacesOnly,NULL,   NULL,  0},
526
527   {"Security Options", P_SEP, P_SEPARATOR},
528
529   {"security",         P_ENUM,    P_GLOBAL, &Globals.security,          NULL,   enum_security, FLAG_BASIC},
530   {"encrypt passwords",P_BOOL,    P_GLOBAL, &Globals.bEncryptPasswords, NULL,   NULL,  FLAG_BASIC},
531   {"update encrypted", P_BOOL,    P_GLOBAL, &Globals.bUpdateEncrypt,    NULL,   NULL,  FLAG_BASIC},
532   {"use rhosts",       P_BOOL,    P_GLOBAL, &Globals.bUseRhosts,        NULL,   NULL,  0},
533   {"map to guest",     P_ENUM,    P_GLOBAL, &Globals.map_to_guest,      NULL,   enum_map_to_guest, 0},
534   {"null passwords",   P_BOOL,    P_GLOBAL, &Globals.bNullPasswords,    NULL,   NULL,  0},
535   {"password server",  P_STRING,  P_GLOBAL, &Globals.szPasswordServer,  NULL,   NULL,  0},
536   {"smb passwd file",  P_STRING,  P_GLOBAL, &Globals.szSMBPasswdFile,   NULL,   NULL,  0},
537 #if USE_SMBFILE_DB
538   {"smb passgrp file", P_STRING,  P_GLOBAL, &Globals.szSMBPassGroupFile, NULL,   NULL,  0},
539 #endif
540 #if USE_SMBGROUP_DB
541   {"smb group file",   P_STRING,  P_GLOBAL, &Globals.szSMBGroupFile,    NULL,   NULL,  0},
542   {"smb alias file",   P_STRING,  P_GLOBAL, &Globals.szSMBAliasFile,    NULL,   NULL,  0},
543 #endif
544   {"hosts equiv",      P_STRING,  P_GLOBAL, &Globals.szHostsEquiv,      NULL,   NULL,  0},
545   {"root directory",   P_STRING,  P_GLOBAL, &Globals.szRootdir,         NULL,   NULL,  0},
546   {"root dir",         P_STRING,  P_GLOBAL, &Globals.szRootdir,         NULL,   NULL,  0},
547   {"root",             P_STRING,  P_GLOBAL, &Globals.szRootdir,         NULL,   NULL,  0},
548   {"passwd program",   P_STRING,  P_GLOBAL, &Globals.szPasswdProgram,   NULL,   NULL,  0},
549   {"passwd chat",      P_STRING,  P_GLOBAL, &Globals.szPasswdChat,      NULL,   NULL,  0},
550   {"passwd chat debug",P_BOOL,    P_GLOBAL, &Globals.bPasswdChatDebug,  NULL,   NULL,  0},
551   {"username map",     P_STRING,  P_GLOBAL, &Globals.szUsernameMap,     NULL,   NULL,  0},
552   {"password level",   P_INTEGER, P_GLOBAL, &Globals.pwordlevel,        NULL,   NULL,  0},
553   {"username level",   P_INTEGER, P_GLOBAL, &Globals.unamelevel,        NULL,   NULL,  0},
554   {"unix password sync", P_BOOL,  P_GLOBAL, &Globals.bUnixPasswdSync,   NULL,   NULL,  0},
555   {"alternate permissions",P_BOOL,P_LOCAL,  &sDefault.bAlternatePerm,   NULL,   NULL,  FLAG_GLOBAL|FLAG_DEPRECATED},
556   {"revalidate",       P_BOOL,    P_LOCAL,  &sDefault.bRevalidate,      NULL,   NULL,  FLAG_GLOBAL},
557   {"username",         P_STRING,  P_LOCAL,  &sDefault.szUsername,       NULL,   NULL,  FLAG_GLOBAL},
558   {"user",             P_STRING,  P_LOCAL,  &sDefault.szUsername,       NULL,   NULL,  0},
559   {"users",            P_STRING,  P_LOCAL,  &sDefault.szUsername,       NULL,   NULL,  0},
560   {"guest account",    P_STRING,  P_LOCAL,  &sDefault.szGuestaccount,   NULL,   NULL,  FLAG_BASIC|FLAG_PRINT|FLAG_GLOBAL},
561   {"invalid users",    P_STRING,  P_LOCAL,  &sDefault.szInvalidUsers,   NULL,   NULL,  FLAG_GLOBAL},
562   {"valid users",      P_STRING,  P_LOCAL,  &sDefault.szValidUsers,     NULL,   NULL,  FLAG_GLOBAL},
563   {"admin users",      P_STRING,  P_LOCAL,  &sDefault.szAdminUsers,     NULL,   NULL,  FLAG_GLOBAL},
564   {"read list",        P_STRING,  P_LOCAL,  &sDefault.readlist,         NULL,   NULL,  FLAG_GLOBAL},
565   {"write list",       P_STRING,  P_LOCAL,  &sDefault.writelist,        NULL,   NULL,  FLAG_GLOBAL},
566   {"force user",       P_STRING,  P_LOCAL,  &sDefault.force_user,       NULL,   NULL,  0},
567   {"force group",      P_STRING,  P_LOCAL,  &sDefault.force_group,      NULL,   NULL,  0},
568   {"group",            P_STRING,  P_LOCAL,  &sDefault.force_group,      NULL,   NULL,  0},
569   {"read only",        P_BOOL,    P_LOCAL,  &sDefault.bRead_only,       NULL,   NULL,  FLAG_BASIC},
570   {"write ok",         P_BOOLREV, P_LOCAL,  &sDefault.bRead_only,       NULL,   NULL,  0},
571   {"writeable",        P_BOOLREV, P_LOCAL,  &sDefault.bRead_only,       NULL,   NULL,  0},
572   {"writable",         P_BOOLREV, P_LOCAL,  &sDefault.bRead_only,       NULL,   NULL,  0},
573   {"create mask",      P_OCTAL,   P_LOCAL,  &sDefault.iCreate_mask,     NULL,   NULL,  FLAG_GLOBAL},
574   {"create mode",      P_OCTAL,   P_LOCAL,  &sDefault.iCreate_mask,     NULL,   NULL,  FLAG_GLOBAL},
575   {"force create mode",P_OCTAL,   P_LOCAL,  &sDefault.iCreate_force_mode,     NULL,   NULL,  FLAG_GLOBAL},
576   {"directory mask",   P_OCTAL,   P_LOCAL,  &sDefault.iDir_mask,        NULL,   NULL,  FLAG_GLOBAL},
577   {"directory mode",   P_OCTAL,   P_LOCAL,  &sDefault.iDir_mask,        NULL,   NULL,  FLAG_GLOBAL},
578   {"force directory mode",   P_OCTAL,   P_LOCAL,  &sDefault.iDir_force_mode,        NULL,   NULL,  FLAG_GLOBAL},
579   {"guest only",       P_BOOL,    P_LOCAL,  &sDefault.bGuest_only,      NULL,   NULL,  0},
580   {"only guest",       P_BOOL,    P_LOCAL,  &sDefault.bGuest_only,      NULL,   NULL,  0},
581   {"guest ok",         P_BOOL,    P_LOCAL,  &sDefault.bGuest_ok,        NULL,   NULL,  FLAG_BASIC|FLAG_PRINT},
582   {"public",           P_BOOL,    P_LOCAL,  &sDefault.bGuest_ok,        NULL,   NULL,  0},
583   {"only user",        P_BOOL,    P_LOCAL,  &sDefault.bOnlyUser,        NULL,   NULL,  0},
584   {"hosts allow",      P_STRING,  P_LOCAL,  &sDefault.szHostsallow,     NULL,   NULL,  FLAG_GLOBAL|FLAG_BASIC|FLAG_PRINT},
585   {"allow hosts",      P_STRING,  P_LOCAL,  &sDefault.szHostsallow,     NULL,   NULL,  0},
586   {"hosts deny",       P_STRING,  P_LOCAL,  &sDefault.szHostsdeny,      NULL,   NULL,  FLAG_GLOBAL|FLAG_BASIC|FLAG_PRINT},
587   {"deny hosts",       P_STRING,  P_LOCAL,  &sDefault.szHostsdeny,      NULL,   NULL,  0},
588
589 #ifdef WITH_SSL
590   {"Secure Socket Layer Options", P_SEP, P_SEPARATOR},
591
592   {"ssl",              P_BOOL,    P_GLOBAL, &Globals.sslEnabled,        NULL,   NULL,  0 },
593   {"ssl hosts",        P_STRING,  P_GLOBAL, &Globals.sslHostsRequire,   NULL,   NULL,  0 },
594   {"ssl hosts resign", P_STRING,  P_GLOBAL, &Globals.sslHostsResign,   NULL,   NULL,  0} ,
595   {"ssl CA certDir",   P_STRING,  P_GLOBAL, &Globals.sslCaCertDir,      NULL,   NULL,  0 },
596   {"ssl CA certFile",  P_STRING,  P_GLOBAL, &Globals.sslCaCertFile,     NULL,   NULL,  0 },
597   {"ssl server cert",  P_STRING,  P_GLOBAL, &Globals.sslCert,           NULL,   NULL,  0 },
598   {"ssl server key",   P_STRING,  P_GLOBAL, &Globals.sslPrivKey,        NULL,   NULL,  0 },
599   {"ssl client cert",  P_STRING,  P_GLOBAL, &Globals.sslClientCert,     NULL,   NULL,  0 },
600   {"ssl client key",   P_STRING,  P_GLOBAL, &Globals.sslClientPrivKey,  NULL,   NULL,  0 },
601   {"ssl require clientcert",  P_BOOL,  P_GLOBAL, &Globals.sslReqClientCert, NULL,   NULL ,  0},
602   {"ssl require servercert",  P_BOOL,  P_GLOBAL, &Globals.sslReqServerCert, NULL,   NULL ,  0},
603   {"ssl ciphers",      P_STRING,  P_GLOBAL, &Globals.sslCiphers,        NULL,   NULL,  0 },
604   {"ssl version",      P_ENUM,    P_GLOBAL, &Globals.sslVersion,        NULL,   enum_ssl_version, 0},
605   {"ssl compatibility", P_BOOL,    P_GLOBAL, &Globals.sslCompatibility, NULL,   NULL,  0 },
606 #endif        /* WITH_SSL */
607
608   {"Logging Options", P_SEP, P_SEPARATOR},
609
610   {"log level",        P_INTEGER, P_GLOBAL, &DEBUGLEVEL,                NULL,   NULL,  FLAG_BASIC},
611   {"debuglevel",       P_INTEGER, P_GLOBAL, &DEBUGLEVEL,                NULL,   NULL,  0},
612   {"syslog",           P_INTEGER, P_GLOBAL, &Globals.syslog,            NULL,   NULL,  0},
613   {"syslog only",      P_BOOL,    P_GLOBAL, &Globals.bSyslogOnly,       NULL,   NULL,  0},
614   {"log file",         P_STRING,  P_GLOBAL, &Globals.szLogFile,         NULL,   NULL,  0},
615   {"max log size",     P_INTEGER, P_GLOBAL, &Globals.max_log_size,      NULL,   NULL,  0},
616   {"timestamp logs",   P_BOOL,    P_GLOBAL, &Globals.bTimestampLogs,    NULL,   NULL,  0},
617   {"debug timestamp",  P_BOOL,    P_GLOBAL, &Globals.bTimestampLogs,    NULL,   NULL,  0},
618   {"status",           P_BOOL,    P_LOCAL,  &sDefault.status,           NULL,   NULL,  FLAG_GLOBAL},
619
620   {"Protocol Options", P_SEP, P_SEPARATOR},
621
622   {"protocol",         P_ENUM,    P_GLOBAL, &Globals.maxprotocol,       NULL,   enum_protocol, 0},
623   {"read bmpx",        P_BOOL,    P_GLOBAL, &Globals.bReadbmpx,         NULL,   NULL,  0},
624   {"read raw",         P_BOOL,    P_GLOBAL, &Globals.bReadRaw,          NULL,   NULL,  0},
625   {"write raw",        P_BOOL,    P_GLOBAL, &Globals.bWriteRaw,         NULL,   NULL,  0},
626   {"nt smb support",   P_BOOL,    P_GLOBAL, &Globals.bNTSmbSupport,    NULL,   NULL,  0},
627   {"nt pipe support",   P_BOOL,    P_GLOBAL, &Globals.bNTPipeSupport,    NULL,   NULL,  0},
628   {"announce version", P_STRING,  P_GLOBAL, &Globals.szAnnounceVersion, NULL,   NULL,  0},
629   {"announce as",      P_ENUM,    P_GLOBAL, &Globals.announce_as,       NULL,   enum_announce_as, 0},
630   {"max mux",          P_INTEGER, P_GLOBAL, &Globals.max_mux,           NULL,   NULL,  0},
631   {"max xmit",         P_INTEGER, P_GLOBAL, &Globals.max_xmit,          NULL,   NULL,  0},
632   {"name resolve order",  P_STRING,  P_GLOBAL, &Globals.szNameResolveOrder,  NULL,   NULL, 0},
633   {"max packet",       P_INTEGER, P_GLOBAL, &Globals.max_packet,        NULL,   NULL,  0},
634   {"packet size",      P_INTEGER, P_GLOBAL, &Globals.max_packet,        NULL,   NULL,  0},
635   {"max ttl",          P_INTEGER, P_GLOBAL, &Globals.max_ttl,           NULL,   NULL,  0},
636   {"max wins ttl",     P_INTEGER, P_GLOBAL, &Globals.max_wins_ttl,      NULL,   NULL,  0},
637   {"min wins ttl",     P_INTEGER, P_GLOBAL, &Globals.min_wins_ttl,      NULL,   NULL,  0},
638   {"time server",      P_BOOL,    P_GLOBAL, &Globals.bTimeServer,       NULL,   NULL,  0},
639
640   {"Tuning Options", P_SEP, P_SEPARATOR},
641
642   {"change notify timeout", P_INTEGER, P_GLOBAL, &Globals.change_notify_timeout, NULL,   NULL,  0},
643   {"deadtime",         P_INTEGER, P_GLOBAL, &Globals.deadtime,          NULL,   NULL,  0},
644   {"getwd cache",      P_BOOL,    P_GLOBAL, &use_getwd_cache,           NULL,   NULL,  0},
645   {"keepalive",        P_INTEGER, P_GLOBAL, &keepalive,                 NULL,   NULL,  0},
646   {"lpq cache time",   P_INTEGER, P_GLOBAL, &Globals.lpqcachetime,      NULL,   NULL,  0},
647   {"max connections",  P_INTEGER, P_LOCAL,  &sDefault.iMaxConnections,  NULL,   NULL,  0},
648   {"max disk size",    P_INTEGER, P_GLOBAL, &Globals.maxdisksize,       NULL,   NULL,  0},
649   {"max open files",   P_INTEGER, P_GLOBAL, &Globals.max_open_files,    NULL,   NULL,  0},
650   {"min print space",  P_INTEGER, P_LOCAL,  &sDefault.iMinPrintSpace,   NULL,   NULL,  0},
651   {"read prediction",  P_BOOL,    P_GLOBAL, &Globals.bReadPrediction,   NULL,   NULL,  0},
652   {"read size",        P_INTEGER, P_GLOBAL, &Globals.ReadSize,          NULL,   NULL,  0},
653   {"shared mem size",  P_INTEGER, P_GLOBAL, &Globals.shmem_size,        NULL,   NULL,  0},
654   {"socket options",   P_GSTRING, P_GLOBAL, user_socket_options,        NULL,   NULL,  0},
655   {"stat cache size",  P_INTEGER, P_GLOBAL, &Globals.stat_cache_size,   NULL,   NULL,  0},
656   {"strict sync",      P_BOOL,    P_LOCAL,  &sDefault.bStrictSync,      NULL,   NULL,  0},
657   {"sync always",      P_BOOL,    P_LOCAL,  &sDefault.bSyncAlways,      NULL,   NULL,  0},
658
659   {"Printing Options", P_SEP, P_SEPARATOR},
660
661   {"load printers",    P_BOOL,    P_GLOBAL, &Globals.bLoadPrinters,     NULL,   NULL,  0},
662   {"printcap name",    P_STRING,  P_GLOBAL, &Globals.szPrintcapname,    NULL,   NULL,  0},
663   {"printcap",         P_STRING,  P_GLOBAL, &Globals.szPrintcapname,    NULL,   NULL,  0},
664   {"printer driver file", P_STRING,  P_GLOBAL, &Globals.szDriverFile,   NULL,   NULL,  0},
665   {"print ok",         P_BOOL,    P_LOCAL,  &sDefault.bPrint_ok,        NULL,   NULL,  0},
666   {"printable",        P_BOOL,    P_LOCAL,  &sDefault.bPrint_ok,        NULL,   NULL,  0},
667   {"postscript",       P_BOOL,    P_LOCAL,  &sDefault.bPostscript,      NULL,   NULL,  FLAG_PRINT},
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   {"lpq command",      P_STRING,  P_LOCAL,  &sDefault.szLpqcommand,     NULL,   NULL,  FLAG_PRINT|FLAG_GLOBAL},
671   {"lprm command",     P_STRING,  P_LOCAL,  &sDefault.szLprmcommand,    NULL,   NULL,  FLAG_PRINT|FLAG_GLOBAL},
672   {"lppause command",  P_STRING,  P_LOCAL,  &sDefault.szLppausecommand, NULL,   NULL,  FLAG_GLOBAL},
673   {"lpresume command", P_STRING,  P_LOCAL,  &sDefault.szLpresumecommand,NULL,   NULL,  FLAG_GLOBAL},
674   {"queuepause command", P_STRING, P_LOCAL, &sDefault.szQueuepausecommand, NULL, NULL, FLAG_GLOBAL},
675   {"queueresume command", P_STRING, P_LOCAL, &sDefault.szQueueresumecommand, NULL, NULL, FLAG_GLOBAL},
676
677   {"printer name",     P_STRING,  P_LOCAL,  &sDefault.szPrintername,    NULL,   NULL,  FLAG_PRINT},
678   {"printer",          P_STRING,  P_LOCAL,  &sDefault.szPrintername,    NULL,   NULL,  0},
679   {"printer driver",   P_STRING,  P_LOCAL,  &sDefault.szPrinterDriver,  NULL,   NULL,  0},
680   {"printer driver location",   P_STRING,  P_LOCAL,  &sDefault.szPrinterDriverLocation,  NULL,   NULL,  FLAG_GLOBAL},
681   {"nt forms file",    P_STRING,  P_GLOBAL, &Globals.szNtForms,         NULL,   NULL,  FLAG_GLOBAL},
682   {"nt printer driver",P_STRING,  P_GLOBAL, &Globals.szNtDriverFile,    NULL,   NULL,  FLAG_GLOBAL},
683
684   {"Filename Handling", P_SEP, P_SEPARATOR},
685   {"strip dot",        P_BOOL,    P_GLOBAL, &Globals.bStripDot,         NULL,   NULL,  0},
686   {"character set",    P_STRING,  P_GLOBAL, &Globals.szCharacterSet,    handle_character_set, NULL,  0},
687   {"mangled stack",    P_INTEGER, P_GLOBAL, &Globals.mangled_stack,     NULL,   NULL,  0},
688   {"coding system",    P_STRING,  P_GLOBAL, &Globals.szCodingSystem,    handle_coding_system, NULL,  0},
689   {"client code page", P_INTEGER, P_GLOBAL, &Globals.client_code_page,  NULL,   NULL,  0},
690   {"default case",     P_ENUM, P_LOCAL,  &sDefault.iDefaultCase,        NULL,   enum_case, 0},
691   {"case sensitive",   P_BOOL,    P_LOCAL,  &sDefault.bCaseSensitive,   NULL,   NULL,  FLAG_GLOBAL},
692   {"casesignames",     P_BOOL,    P_LOCAL,  &sDefault.bCaseSensitive,   NULL,   NULL,  0},
693   {"preserve case",    P_BOOL,    P_LOCAL,  &sDefault.bCasePreserve,    NULL,   NULL,  FLAG_GLOBAL},
694   {"short preserve case",P_BOOL,  P_LOCAL,  &sDefault.bShortCasePreserve,NULL,   NULL,  FLAG_GLOBAL},
695   {"mangle case",      P_BOOL,    P_LOCAL,  &sDefault.bCaseMangle,      NULL,   NULL,  FLAG_GLOBAL},
696   {"mangling char",    P_CHAR,    P_LOCAL,  &sDefault.magic_char,       NULL,   NULL,  FLAG_GLOBAL},
697   {"hide dot files",   P_BOOL,    P_LOCAL,  &sDefault.bHideDotFiles,    NULL,   NULL,  FLAG_GLOBAL},
698   {"delete veto files",P_BOOL,    P_LOCAL,  &sDefault.bDeleteVetoFiles, NULL,   NULL,  FLAG_GLOBAL},
699   {"veto files",       P_STRING,  P_LOCAL,  &sDefault.szVetoFiles,      NULL,   NULL,  FLAG_GLOBAL},
700   {"hide files",       P_STRING,  P_LOCAL,  &sDefault.szHideFiles,      NULL,   NULL,  FLAG_GLOBAL},
701   {"veto oplock files",P_STRING,  P_LOCAL,  &sDefault.szVetoOplockFiles,NULL,   NULL,  FLAG_GLOBAL},
702   {"map system",       P_BOOL,    P_LOCAL,  &sDefault.bMap_system,      NULL,   NULL,  FLAG_GLOBAL},
703   {"map hidden",       P_BOOL,    P_LOCAL,  &sDefault.bMap_hidden,      NULL,   NULL,  FLAG_GLOBAL},
704   {"map archive",      P_BOOL,    P_LOCAL,  &sDefault.bMap_archive,     NULL,   NULL,  FLAG_GLOBAL},
705   {"mangled names",    P_BOOL,    P_LOCAL,  &sDefault.bMangledNames,    NULL,   NULL,  FLAG_GLOBAL},
706   {"mangled map",      P_STRING,  P_LOCAL,  &sDefault.szMangledMap,     NULL,   NULL,  FLAG_GLOBAL},
707   {"stat cache",       P_BOOL,    P_GLOBAL, &Globals.bStatCache,        NULL,   NULL,  0},
708
709   {"Domain Options", P_SEP, P_SEPARATOR},
710
711   {"local group map",   P_STRING, P_GLOBAL, &Globals.szAliasnameMap,     NULL,   NULL,  0},
712   {"domain group map",  P_STRING, P_GLOBAL, &Globals.szGroupnameMap,     NULL,   NULL,  0},
713   {"builtin group map", P_STRING, P_GLOBAL, &Globals.szBuiltinnameMap,   NULL,   NULL,  0},
714   {"domain user map",   P_STRING, P_GLOBAL, &Globals.szNTusernameMap,     NULL,   NULL,  0},
715   {"machine password timeout", P_INTEGER, P_GLOBAL, &Globals.machine_password_timeout,  NULL,   NULL,  0},
716
717   {"Logon Options", P_SEP, P_SEPARATOR},
718
719   {"logon script",     P_STRING,  P_GLOBAL, &Globals.szLogonScript,     NULL,   NULL,  0},
720   {"logon path",       P_STRING,  P_GLOBAL, &Globals.szLogonPath,       NULL,   NULL,  0},
721   {"logon drive",      P_STRING,  P_GLOBAL, &Globals.szLogonDrive,      NULL,   NULL,  0},
722   {"logon home",       P_STRING,  P_GLOBAL, &Globals.szLogonHome,       NULL,   NULL,  0},
723   {"domain logons",    P_BOOL,    P_GLOBAL, &Globals.bDomainLogons,     NULL,   NULL,  0},
724
725   {"Browse Options", P_SEP, P_SEPARATOR},
726
727   {"os level",         P_INTEGER, P_GLOBAL, &Globals.os_level,          NULL,   NULL,  FLAG_BASIC},
728   {"lm announce",      P_ENUM,    P_GLOBAL, &Globals.lm_announce,       NULL,   enum_bool_auto, 0},
729   {"lm interval",      P_INTEGER, P_GLOBAL, &Globals.lm_interval,       NULL,   NULL,  0},
730   {"preferred master", P_ENUM,    P_GLOBAL, &Globals.bPreferredMaster,  NULL,   enum_bool_auto,  FLAG_BASIC},
731   {"prefered master",  P_ENUM,    P_GLOBAL, &Globals.bPreferredMaster,  NULL,   enum_bool_auto,  FLAG_HIDE},
732   {"local master",     P_BOOL,    P_GLOBAL, &Globals.bLocalMaster,      NULL,   NULL,  FLAG_BASIC},
733   {"domain master",    P_ENUM,    P_GLOBAL, &Globals.bDomainMaster,     NULL,   enum_bool_auto,  FLAG_BASIC},
734   {"browse list",      P_BOOL,    P_GLOBAL, &Globals.bBrowseList,       NULL,   NULL,  0},
735   {"browseable",       P_BOOL,    P_LOCAL,  &sDefault.bBrowseable,      NULL,   NULL,  0},
736   {"browsable",        P_BOOL,    P_LOCAL,  &sDefault.bBrowseable,      NULL,   NULL,  0},
737
738   {"WINS Options", P_SEP, P_SEPARATOR},
739
740   {"dns proxy",        P_BOOL,    P_GLOBAL, &Globals.bDNSproxy,         NULL,   NULL,  0},
741   {"wins proxy",       P_BOOL,    P_GLOBAL, &Globals.bWINSproxy,        NULL,   NULL,  0},
742   {"wins server",      P_STRING,  P_GLOBAL, &Globals.szWINSserver,      NULL,   NULL,  FLAG_BASIC},
743   {"wins support",     P_BOOL,    P_GLOBAL, &Globals.bWINSsupport,      NULL,   NULL,  FLAG_BASIC},
744
745   {"Locking Options", P_SEP, P_SEPARATOR},
746
747   {"blocking locks",   P_BOOL,    P_LOCAL,  &sDefault.bBlockingLocks,    NULL,   NULL,  0},
748   {"fake oplocks",     P_BOOL,    P_LOCAL,  &sDefault.bFakeOplocks,     NULL,   NULL,  0},
749   {"kernel oplocks",   P_BOOL,    P_GLOBAL, &Globals.bKernelOplocks,    NULL,   NULL,  FLAG_GLOBAL},
750   {"locking",          P_BOOL,    P_LOCAL,  &sDefault.bLocking,         NULL,   NULL,  FLAG_GLOBAL},
751   {"ole locking compatibility",   P_BOOL,    P_GLOBAL,  &Globals.bOleLockingCompat,   NULL,   NULL,  FLAG_GLOBAL},
752   {"oplocks",          P_BOOL,    P_LOCAL,  &sDefault.bOpLocks,         NULL,   NULL,  FLAG_GLOBAL},
753   {"strict locking",   P_BOOL,    P_LOCAL,  &sDefault.bStrictLocking,   NULL,   NULL,  FLAG_GLOBAL},
754   {"share modes",      P_BOOL,    P_LOCAL,  &sDefault.bShareModes,      NULL,   NULL,  FLAG_GLOBAL},
755
756 #ifdef WITH_LDAP
757   {"Ldap Options", P_SEP, P_SEPARATOR},
758
759   {"ldap server",      P_STRING,  P_GLOBAL, &Globals.szLdapServer,      NULL,   NULL,  0},
760   {"ldap port",        P_INTEGER, P_GLOBAL, &Globals.ldap_port,         NULL,   NULL,  0},
761   {"ldap suffix",      P_STRING,  P_GLOBAL, &Globals.szLdapSuffix,      NULL,   NULL,  0},
762   {"ldap bind as",     P_STRING,  P_GLOBAL, &Globals.szLdapBindAs,      NULL,   NULL,  0},
763   {"ldap passwd file", P_STRING,  P_GLOBAL, &Globals.szLdapPasswdFile,  NULL,   NULL,  0},
764 #endif /* WITH_LDAP */
765
766 #if defined(HAVE_MYSQL_H) && defined(WITH_MYSQLSAM)
767   {"MySQL Options", P_SEP, P_SEPARATOR},
768   {"mysql host",        P_STRING, P_GLOBAL, &Globals.sMysqlHost,        NULL,   NULL,  0},
769   {"mysql user",        P_STRING, P_GLOBAL, &Globals.sMysqlUser,        NULL,   NULL,  0},
770   {"mysql pass file",   P_STRING, P_GLOBAL, &Globals.sMysqlPassFile,    NULL,   NULL,  0},
771   {"mysql database",    P_STRING, P_GLOBAL, &Globals.sMysqlDatabase,    NULL,   NULL,  0},
772   {"mysql table",       P_STRING, P_GLOBAL, &Globals.sMysqlTable,       NULL,   NULL,  0},
773 #endif /* MYSQL */
774
775   {"Miscellaneous Options", P_SEP, P_SEPARATOR},
776
777   {"smbrun",           P_STRING,  P_GLOBAL, &Globals.szSmbrun,          NULL,   NULL,  0},
778   {"config file",      P_STRING,  P_GLOBAL, &Globals.szConfigFile,      NULL,   NULL,  FLAG_HIDE},
779   {"preload",          P_STRING,  P_GLOBAL, &Globals.szAutoServices,    NULL,   NULL,  0},
780   {"auto services",    P_STRING,  P_GLOBAL, &Globals.szAutoServices,    NULL,   NULL,  0},
781   {"lock dir",         P_STRING,  P_GLOBAL, &Globals.szLockDir,         NULL,   NULL,  0},
782   {"lock directory",   P_STRING,  P_GLOBAL, &Globals.szLockDir,         NULL,   NULL,  0},
783   {"default service",  P_STRING,  P_GLOBAL, &Globals.szDefaultService,  NULL,   NULL,  0},
784   {"default",          P_STRING,  P_GLOBAL, &Globals.szDefaultService,  NULL,   NULL,  0},
785   {"message command",  P_STRING,  P_GLOBAL, &Globals.szMsgCommand,      NULL,   NULL,  0},
786   {"dfree command",    P_STRING,  P_GLOBAL, &Globals.szDfree,           NULL,   NULL,  0},
787   {"valid chars",      P_STRING,  P_GLOBAL, &Globals.szValidChars,      handle_valid_chars, NULL,  0},
788   {"remote announce",  P_STRING,  P_GLOBAL, &Globals.szRemoteAnnounce,  NULL,   NULL,  0},
789   {"remote browse sync",P_STRING, P_GLOBAL, &Globals.szRemoteBrowseSync,NULL,   NULL,  0},
790   {"socket address",   P_STRING,  P_GLOBAL, &Globals.szSocketAddress,   NULL,   NULL,  0},
791   {"homedir map",      P_STRING,  P_GLOBAL, &Globals.szNISHomeMapName,  NULL,   NULL,  0},
792   {"time offset",      P_INTEGER, P_GLOBAL, &extra_time_offset,         NULL,   NULL,  0},
793   {"unix realname",    P_BOOL,    P_GLOBAL, &Globals.bUnixRealname,     NULL,   NULL,  0},
794   {"NIS homedir",      P_BOOL,    P_GLOBAL, &Globals.bNISHomeMap,       NULL,   NULL,  0},
795   {"-valid",           P_BOOL,    P_LOCAL,  &sDefault.valid,            NULL,   NULL,  FLAG_HIDE},
796   {"copy",             P_STRING,  P_LOCAL,  &sDefault.szCopy,           handle_copy, NULL,  FLAG_HIDE},
797   {"include",          P_STRING,  P_LOCAL,  &sDefault.szInclude,        handle_include, NULL,  FLAG_HIDE},
798   {"exec",             P_STRING,  P_LOCAL,  &sDefault.szPreExec,        NULL,   NULL,  0},
799   {"preexec",          P_STRING,  P_LOCAL,  &sDefault.szPreExec,        NULL,   NULL,  0},
800   {"postexec",         P_STRING,  P_LOCAL,  &sDefault.szPostExec,       NULL,   NULL,  0},
801   {"root preexec",     P_STRING,  P_LOCAL,  &sDefault.szRootPreExec,    NULL,   NULL,  0},
802   {"root postexec",    P_STRING,  P_LOCAL,  &sDefault.szRootPostExec,   NULL,   NULL,  0},
803   {"available",        P_BOOL,    P_LOCAL,  &sDefault.bAvailable,       NULL,   NULL,  0},
804   {"volume",           P_STRING,  P_LOCAL,  &sDefault.volume,           NULL,   NULL,  0},
805   {"fstype",           P_STRING,  P_LOCAL,  &sDefault.fstype,           NULL,   NULL,  0},
806   {"vfs object",       P_STRING,  P_LOCAL,  &sDefault.vfsObjectFile,    handle_vfs_object,   NULL,  0},
807   {"set directory",    P_BOOLREV, P_LOCAL,  &sDefault.bNo_set_dir,      NULL,   NULL,  0},
808   {"wide links",       P_BOOL,    P_LOCAL,  &sDefault.bWidelinks,       NULL,   NULL,  FLAG_GLOBAL},
809   {"follow symlinks",  P_BOOL,    P_LOCAL,  &sDefault.bSymlinks,        NULL,   NULL,  FLAG_GLOBAL},
810   {"dont descend",     P_STRING,  P_LOCAL,  &sDefault.szDontdescend,    NULL,   NULL,  0},
811   {"magic script",     P_STRING,  P_LOCAL,  &sDefault.szMagicScript,    NULL,   NULL,  0},
812   {"magic output",     P_STRING,  P_LOCAL,  &sDefault.szMagicOutput,    NULL,   NULL,  0},
813   {"delete readonly",  P_BOOL,    P_LOCAL,  &sDefault.bDeleteReadonly,  NULL,   NULL,  FLAG_GLOBAL},
814   {"dos filetimes",    P_BOOL,    P_LOCAL,  &sDefault.bDosFiletimes,    NULL,   NULL,  FLAG_GLOBAL},
815   {"dos filetime resolution",P_BOOL,P_LOCAL,&sDefault.bDosFiletimeResolution,   NULL,  NULL,  FLAG_GLOBAL},
816   
817   {"fake directory create times", P_BOOL,P_LOCAL,  &sDefault.bFakeDirCreateTimes, NULL,   NULL, FLAG_GLOBAL},
818   {"panic action",     P_STRING,  P_GLOBAL, &Globals.szPanicAction,     NULL,   NULL,  0},
819
820   {NULL,               P_BOOL,    P_NONE,   NULL,                       NULL,   NULL, 0}
821 };
822
823
824
825 /***************************************************************************
826 Initialise the global parameter structure.
827 ***************************************************************************/
828 static void init_globals(void)
829 {
830   static BOOL done_init = False;
831   pstring s;
832
833   if (!done_init)
834     {
835       int i;
836       bzero((void *)&Globals,sizeof(Globals));
837
838       for (i = 0; parm_table[i].label; i++) 
839         if ((parm_table[i].type == P_STRING ||
840              parm_table[i].type == P_USTRING) && 
841             parm_table[i].ptr)
842           string_init(parm_table[i].ptr,"");
843
844       string_set(&sDefault.szGuestaccount, GUEST_ACCOUNT);
845       string_set(&sDefault.szPrinterDriver, "NULL");
846       string_set(&sDefault.fstype, FSTYPE_STRING);
847
848       done_init = True;
849     }
850
851
852   DEBUG(3,("Initialising global parameters\n"));
853
854   string_set(&Globals.szSMBPasswdFile, SMB_PASSWD_FILE);
855 #if USE_SMBFILE_DB
856   string_set(&Globals.szSMBPassGroupFile, SMB_PASSGRP_FILE);
857 #endif
858 #if USE_SMBGROUP_DB
859   string_set(&Globals.szSMBGroupFile, SMB_GROUP_FILE);
860   string_set(&Globals.szSMBAliasFile, SMB_ALIAS_FILE);
861 #endif
862   string_set(&Globals.szPasswdChat,"*old*password* %o\\n *new*password* %n\\n *new*password* %n\\n *changed*");
863   string_set(&Globals.szWorkGroup, WORKGROUP);
864   string_set(&Globals.szPasswdProgram, PASSWD_PROGRAM);
865   string_set(&Globals.szPrintcapname, PRINTCAP_NAME);
866   string_set(&Globals.szDriverFile, DRIVERFILE);
867   string_set(&Globals.szNtForms, FORMSFILE);
868   string_set(&Globals.szNtDriverFile, NTDRIVERSDIR);
869   string_set(&Globals.szLockDir, LOCKDIR);
870   string_set(&Globals.szRootdir, "/");
871   string_set(&Globals.szSmbrun, SMBRUN);
872   string_set(&Globals.szSocketAddress, "0.0.0.0");
873   pstrcpy(s, "Samba ");
874   pstrcat(s, VERSION);
875   string_set(&Globals.szServerString,s);
876   slprintf(s,sizeof(s)-1, "%d.%d", DEFAULT_MAJOR_VERSION, DEFAULT_MINOR_VERSION);
877   string_set(&Globals.szAnnounceVersion,s);
878
879   pstrcpy(user_socket_options, DEFAULT_SOCKET_OPTIONS);
880
881   string_set(&Globals.szLogonDrive, "");
882   /* %N is the NIS auto.home server if -DAUTOHOME is used, else same as %L */
883   string_set(&Globals.szLogonHome, "\\\\%N\\%U");
884   string_set(&Globals.szLogonPath, "\\\\%N\\%U\\profile");
885
886   string_set(&Globals.szNameResolveOrder, "lmhosts host wins bcast");
887
888   Globals.bLoadPrinters = True;
889   Globals.bUseRhosts = False;
890   Globals.max_packet = 65535;
891   Globals.mangled_stack = 50;
892   Globals.max_xmit = 65535;
893   Globals.max_mux = 50; /* This is *needed* for profile support. */
894   Globals.lpqcachetime = 10;
895   Globals.pwordlevel = 0;
896   Globals.unamelevel = 0;
897   Globals.deadtime = 0;
898   Globals.max_log_size = 5000;
899   Globals.max_open_files = MAX_OPEN_FILES;
900   Globals.maxprotocol = PROTOCOL_NT1;
901   Globals.security = SEC_USER;
902   Globals.bEncryptPasswords = False;
903   Globals.bUpdateEncrypt = False;
904   Globals.bReadRaw = True;
905   Globals.bWriteRaw = True;
906   Globals.bReadPrediction = False;
907   Globals.bReadbmpx = True;
908   Globals.bNullPasswords = False;
909   Globals.bStripDot = False;
910   Globals.syslog = 1;
911   Globals.bSyslogOnly = False;
912   Globals.bTimestampLogs = True;
913   Globals.os_level = 32;
914   Globals.max_ttl = 60*60*24*3; /* 3 days default. */
915   Globals.max_wins_ttl = 60*60*24*6; /* 6 days default. */
916   Globals.min_wins_ttl = 60*60*6; /* 6 hours default. */
917   Globals.machine_password_timeout = 60*60*24*7; /* 7 days default. */
918   Globals.change_notify_timeout = 60; /* 1 minute default. */
919   Globals.ReadSize = 16*1024;
920   Globals.lm_announce = 2;   /* = Auto: send only if LM clients found */
921   Globals.lm_interval = 60;
922   Globals.shmem_size = SHMEM_SIZE;
923   Globals.stat_cache_size = 50; /* Number of stat translations we'll keep */
924   Globals.announce_as = ANNOUNCE_AS_NT;
925   Globals.bUnixRealname = False;
926 #if (defined(HAVE_NETGROUP) && defined(WITH_AUTOMOUNT))
927   Globals.bNISHomeMap = False;
928 #ifdef WITH_NISPLUS_HOME
929   string_set(&Globals.szNISHomeMapName, "auto_home.org_dir");
930 #else
931   string_set(&Globals.szNISHomeMapName, "auto.home");
932 #endif
933 #endif
934   Globals.client_code_page = DEFAULT_CLIENT_CODE_PAGE;
935   Globals.bTimeServer = False;
936   Globals.bBindInterfacesOnly = False;
937   Globals.bUnixPasswdSync = False;
938   Globals.bPasswdChatDebug = False;
939   Globals.bOleLockingCompat = True;
940   Globals.bNTSmbSupport = True; /* Do NT SMB's by default. */
941   Globals.bNTPipeSupport = True; /* Do NT pipes by default. */
942   Globals.bStatCache = True; /* use stat cache by default */
943   Globals.map_to_guest = 0; /* By Default, "Never" */
944
945 #ifdef WITH_LDAP
946   /* default values for ldap */
947   string_set(&Globals.szLdapServer, "localhost");
948   Globals.ldap_port=389;
949 #endif /* WITH_LDAP */
950
951 #ifdef WITH_SSL
952   Globals.sslVersion = SMB_SSL_V23;
953
954   /*
955    * Most of the next variables should be string_set!
956    */
957
958   string_set(&Globals.sslHostsRequire, NULL);
959   string_set(&Globals.sslHostsResign, NULL);
960   string_set(&Globals.sslCaCertDir, NULL);
961   string_set(&Globals.sslCaCertFile, NULL);
962   string_set(&Globals.sslCert, NULL);
963   string_set(&Globals.sslPrivKey, NULL);
964   string_set(&Globals.sslClientCert, NULL);
965   string_set(&Globals.sslClientPrivKey, NULL);
966   string_set(&Globals.sslCiphers, NULL);
967   Globals.sslEnabled = False;
968   Globals.sslReqClientCert = False;
969   Globals.sslReqServerCert = False;
970   Globals.sslCompatibility = False;
971 #endif        /* WITH_SSL */
972
973 /* these parameters are set to defaults that are more appropriate
974    for the increasing samba install base:
975
976    as a member of the workgroup, that will possibly become a
977    _local_ master browser (lm = True).  this is opposed to a forced
978    local master browser startup (pm = True).
979
980    doesn't provide WINS server service by default (wsupp = False),
981    and doesn't provide domain master browser services by default, either.
982
983 */
984
985   Globals.bPreferredMaster = Auto; /* depending on bDomainMaster */
986   Globals.bLocalMaster = True;
987   Globals.bDomainMaster = Auto; /* depending on bDomainLogons */
988   Globals.bDomainLogons = False;
989   Globals.bBrowseList = True;
990   Globals.bWINSsupport = False;
991   Globals.bWINSproxy = False;
992
993   Globals.bDNSproxy = True;
994
995   /*
996    * smbd will check at runtime to see if this value
997    * will really be used or not.
998    */
999   Globals.bKernelOplocks = True;
1000
1001 #if defined(HAVE_MYSQL_H) && defined(WITH_MYSQLSAM)
1002   string_set(&Globals.sMysqlHost,"localhost");
1003   string_set(&Globals.sMysqlUser,"root");
1004   string_set(&Globals.sMysqlPassFile,NULL);
1005   string_set(&Globals.sMysqlDatabase,"samba");
1006   string_set(&Globals.sMysqlTable,"smbpasswd");
1007 #endif
1008
1009   /*
1010    * This must be done last as it checks the value in 
1011    * client_code_page.
1012    */
1013
1014   interpret_coding_system(KANJI);
1015 }
1016
1017 /***************************************************************************
1018 check if a string is initialised and if not then initialise it
1019 ***************************************************************************/
1020 static void string_initial(char **s,char *v)
1021 {
1022   if (!*s || !**s)
1023     string_init(s,v);
1024 }
1025
1026
1027 /***************************************************************************
1028 Initialise the sDefault parameter structure.
1029 ***************************************************************************/
1030 static void init_locals(void)
1031 {
1032   /* choose defaults depending on the type of printing */
1033   switch (sDefault.iPrinting)
1034     {
1035     case PRINT_BSD:
1036     case PRINT_AIX:
1037     case PRINT_PLP:
1038       string_initial(&sDefault.szLpqcommand,"lpq -P%p");
1039       string_initial(&sDefault.szLprmcommand,"lprm -P%p %j");
1040       string_initial(&sDefault.szPrintcommand,"lpr -r -P%p %s");
1041       break;
1042       
1043     case PRINT_LPRNG:
1044       string_initial(&sDefault.szLpqcommand,"lpq -P%p");
1045       string_initial(&sDefault.szLprmcommand,"lprm -P%p %j");
1046       string_initial(&sDefault.szPrintcommand,"lpr -r -P%p %s");
1047       string_initial(&sDefault.szQueuepausecommand, "lpc stop %p");
1048       string_initial(&sDefault.szQueueresumecommand, "lpc start %p");
1049       string_initial(&sDefault.szLppausecommand,"lpc hold %p %j");
1050       string_initial(&sDefault.szLpresumecommand,"lpc release %p %j");
1051       break;
1052
1053     case PRINT_SYSV:
1054     case PRINT_HPUX:
1055       string_initial(&sDefault.szLpqcommand,"lpstat -o%p");
1056       string_initial(&sDefault.szLprmcommand,"cancel %p-%j");
1057       string_initial(&sDefault.szPrintcommand,"lp -c -d%p %s; rm %s");
1058 #ifdef SYSV
1059       string_initial(&sDefault.szLppausecommand,"lp -i %p-%j -H hold");
1060       string_initial(&sDefault.szLpresumecommand,"lp -i %p-%j -H resume");
1061       string_initial(&sDefault.szQueuepausecommand, "lpc stop %p");
1062       string_initial(&sDefault.szQueueresumecommand, "lpc start %p");
1063 #else /* SYSV */
1064       string_initial(&sDefault.szQueuepausecommand, "disable %p");
1065       string_initial(&sDefault.szQueueresumecommand, "enable %p");
1066 #endif /* SYSV */
1067       break;
1068
1069     case PRINT_QNX:
1070       string_initial(&sDefault.szLpqcommand,"lpq -P%p");
1071       string_initial(&sDefault.szLprmcommand,"lprm -P%p %j");
1072       string_initial(&sDefault.szPrintcommand,"lp -r -P%p %s");
1073       break;
1074
1075     case PRINT_SOFTQ:
1076       string_initial(&sDefault.szLpqcommand,"qstat -l -d%p");
1077       string_initial(&sDefault.szLprmcommand,"qstat -s -j%j -c");
1078       string_initial(&sDefault.szPrintcommand,"lp -d%p -s %s; rm %s");
1079       string_initial(&sDefault.szLppausecommand,"qstat -s -j%j -h");
1080       string_initial(&sDefault.szLpresumecommand,"qstat -s -j%j -r");
1081       break;
1082       
1083     }
1084 }
1085
1086
1087 /******************************************************************* a
1088 convenience routine to grab string parameters into a rotating buffer,
1089 and run standard_sub_basic on them. The buffers can be written to by
1090 callers without affecting the source string.
1091 ********************************************************************/
1092 static char *lp_string(char *s)
1093 {
1094   static char *bufs[10];
1095   static int buflen[10];
1096   static int next = -1;  
1097   char *ret;
1098   int i;
1099   int len = s?strlen(s):0;
1100
1101   if (next == -1) {
1102     /* initialisation */
1103     for (i=0;i<10;i++) {
1104       bufs[i] = NULL;
1105       buflen[i] = 0;
1106     }
1107     next = 0;
1108   }
1109
1110   len = MAX(len+100,sizeof(pstring)); /* the +100 is for some
1111                                          substitution room */
1112
1113   if (buflen[next] != len) {
1114     buflen[next] = len;
1115     if (bufs[next]) free(bufs[next]);
1116     bufs[next] = (char *)malloc(len);
1117     if (!bufs[next]) {
1118       DEBUG(0,("out of memory in lp_string()"));
1119       exit(1);
1120     }
1121   } 
1122
1123   ret = &bufs[next][0];
1124   next = (next+1)%10;
1125
1126   if (!s) 
1127     *ret = 0;
1128   else
1129     StrCpy(ret,s);
1130
1131   trim_string(ret, "\"", "\"");
1132
1133   standard_sub_basic(ret);
1134   return(ret);
1135 }
1136
1137
1138 /*
1139    In this section all the functions that are used to access the 
1140    parameters from the rest of the program are defined 
1141 */
1142
1143 #define FN_GLOBAL_STRING(fn_name,ptr) \
1144  char *fn_name(void) {return(lp_string(*(char **)(ptr) ? *(char **)(ptr) : ""));}
1145 #define FN_GLOBAL_BOOL(fn_name,ptr) \
1146  BOOL fn_name(void) {return(*(BOOL *)(ptr));}
1147 #define FN_GLOBAL_CHAR(fn_name,ptr) \
1148  char fn_name(void) {return(*(char *)(ptr));}
1149 #define FN_GLOBAL_INTEGER(fn_name,ptr) \
1150  int fn_name(void) {return(*(int *)(ptr));}
1151
1152 #define FN_LOCAL_STRING(fn_name,val) \
1153  char *fn_name(int i) {return(lp_string((LP_SNUM_OK(i)&&pSERVICE(i)->val)?pSERVICE(i)->val : sDefault.val));}
1154 #define FN_LOCAL_BOOL(fn_name,val) \
1155  BOOL fn_name(int i) {return(LP_SNUM_OK(i)? pSERVICE(i)->val : sDefault.val);}
1156 #define FN_LOCAL_CHAR(fn_name,val) \
1157  char fn_name(int i) {return(LP_SNUM_OK(i)? pSERVICE(i)->val : sDefault.val);}
1158 #define FN_LOCAL_INTEGER(fn_name,val) \
1159  int fn_name(int i) {return(LP_SNUM_OK(i)? pSERVICE(i)->val : sDefault.val);}
1160
1161 FN_GLOBAL_STRING(lp_logfile,&Globals.szLogFile)
1162 FN_GLOBAL_STRING(lp_smbrun,&Globals.szSmbrun)
1163 FN_GLOBAL_STRING(lp_configfile,&Globals.szConfigFile)
1164 FN_GLOBAL_STRING(lp_smb_passwd_file,&Globals.szSMBPasswdFile)
1165 #if USE_SMBFILE_DB
1166 FN_GLOBAL_STRING(lp_smb_passgrp_file,&Globals.szSMBPassGroupFile)
1167 #endif
1168 #if USE_SMBGROUP_DB
1169 FN_GLOBAL_STRING(lp_smb_group_file,&Globals.szSMBGroupFile)
1170 FN_GLOBAL_STRING(lp_smb_alias_file,&Globals.szSMBAliasFile)
1171 #endif
1172 FN_GLOBAL_STRING(lp_serverstring,&Globals.szServerString)
1173 FN_GLOBAL_STRING(lp_printcapname,&Globals.szPrintcapname)
1174 FN_GLOBAL_STRING(lp_lockdir,&Globals.szLockDir)
1175 FN_GLOBAL_STRING(lp_rootdir,&Globals.szRootdir)
1176 FN_GLOBAL_STRING(lp_defaultservice,&Globals.szDefaultService)
1177 FN_GLOBAL_STRING(lp_msg_command,&Globals.szMsgCommand)
1178 FN_GLOBAL_STRING(lp_hosts_equiv,&Globals.szHostsEquiv)
1179 FN_GLOBAL_STRING(lp_auto_services,&Globals.szAutoServices)
1180 FN_GLOBAL_STRING(lp_passwd_program,&Globals.szPasswdProgram)
1181 FN_GLOBAL_STRING(lp_passwd_chat,&Globals.szPasswdChat)
1182 FN_GLOBAL_STRING(lp_passwordserver,&Globals.szPasswordServer)
1183 FN_GLOBAL_STRING(lp_name_resolve_order,&Globals.szNameResolveOrder)
1184 FN_GLOBAL_STRING(lp_workgroup,&Globals.szWorkGroup)
1185 FN_GLOBAL_STRING(lp_username_map,&Globals.szUsernameMap)
1186 FN_GLOBAL_STRING(lp_aliasname_map,&Globals.szAliasnameMap)
1187 FN_GLOBAL_STRING(lp_groupname_map,&Globals.szGroupnameMap)
1188 FN_GLOBAL_STRING(lp_builtinname_map,&Globals.szBuiltinnameMap)
1189 FN_GLOBAL_STRING(lp_ntusrname_map,&Globals.szNTusernameMap)
1190 FN_GLOBAL_STRING(lp_logon_script,&Globals.szLogonScript) 
1191 FN_GLOBAL_STRING(lp_logon_path,&Globals.szLogonPath) 
1192 FN_GLOBAL_STRING(lp_logon_drive,&Globals.szLogonDrive) 
1193 FN_GLOBAL_STRING(lp_logon_home,&Globals.szLogonHome) 
1194 FN_GLOBAL_STRING(lp_remote_announce,&Globals.szRemoteAnnounce) 
1195 FN_GLOBAL_STRING(lp_remote_browse_sync,&Globals.szRemoteBrowseSync) 
1196 FN_GLOBAL_STRING(lp_wins_server,&Globals.szWINSserver)
1197 FN_GLOBAL_STRING(lp_interfaces,&Globals.szInterfaces)
1198 FN_GLOBAL_STRING(lp_socket_address,&Globals.szSocketAddress)
1199 FN_GLOBAL_STRING(lp_nis_home_map_name,&Globals.szNISHomeMapName)
1200 static FN_GLOBAL_STRING(lp_announce_version,&Globals.szAnnounceVersion)
1201 FN_GLOBAL_STRING(lp_netbios_aliases,&Globals.szNetbiosAliases)
1202 FN_GLOBAL_STRING(lp_driverfile,&Globals.szDriverFile)
1203 FN_GLOBAL_STRING(lp_panic_action,&Globals.szPanicAction)
1204 FN_GLOBAL_STRING(lp_nt_forms,&Globals.szNtForms)
1205 FN_GLOBAL_STRING(lp_nt_drivers_file,&Globals.szNtDriverFile)
1206
1207 #ifdef WITH_LDAP
1208 FN_GLOBAL_STRING(lp_ldap_server,&Globals.szLdapServer);
1209 FN_GLOBAL_STRING(lp_ldap_suffix,&Globals.szLdapSuffix);
1210 FN_GLOBAL_STRING(lp_ldap_bind_as,&Globals.szLdapBindAs);
1211 FN_GLOBAL_STRING(lp_ldap_passwd_file,&Globals.szLdapPasswdFile);
1212 #endif /* WITH_LDAP */
1213
1214 #ifdef WITH_SSL
1215 FN_GLOBAL_INTEGER(lp_ssl_version,&Globals.sslVersion);
1216 FN_GLOBAL_STRING(lp_ssl_hosts,&Globals.sslHostsRequire);
1217 FN_GLOBAL_STRING(lp_ssl_hosts_resign,&Globals.sslHostsResign);
1218 FN_GLOBAL_STRING(lp_ssl_cacertdir,&Globals.sslCaCertDir);
1219 FN_GLOBAL_STRING(lp_ssl_cacertfile,&Globals.sslCaCertFile);
1220 FN_GLOBAL_STRING(lp_ssl_cert,&Globals.sslCert);
1221 FN_GLOBAL_STRING(lp_ssl_privkey,&Globals.sslPrivKey);
1222 FN_GLOBAL_STRING(lp_ssl_client_cert,&Globals.sslClientCert);
1223 FN_GLOBAL_STRING(lp_ssl_client_privkey,&Globals.sslClientPrivKey);
1224 FN_GLOBAL_STRING(lp_ssl_ciphers,&Globals.sslCiphers);
1225 FN_GLOBAL_BOOL(lp_ssl_enabled,&Globals.sslEnabled);
1226 FN_GLOBAL_BOOL(lp_ssl_reqClientCert,&Globals.sslReqClientCert);
1227 FN_GLOBAL_BOOL(lp_ssl_reqServerCert,&Globals.sslReqServerCert);
1228 FN_GLOBAL_BOOL(lp_ssl_compatibility,&Globals.sslCompatibility);
1229 #endif        /* WITH_SSL */
1230
1231 FN_GLOBAL_BOOL(lp_dns_proxy,&Globals.bDNSproxy)
1232 FN_GLOBAL_BOOL(lp_wins_support,&Globals.bWINSsupport)
1233 FN_GLOBAL_BOOL(lp_we_are_a_wins_server,&Globals.bWINSsupport)
1234 FN_GLOBAL_BOOL(lp_wins_proxy,&Globals.bWINSproxy)
1235 FN_GLOBAL_BOOL(lp_local_master,&Globals.bLocalMaster)
1236 FN_GLOBAL_BOOL(lp_domain_logons,&Globals.bDomainLogons)
1237 FN_GLOBAL_BOOL(lp_load_printers,&Globals.bLoadPrinters)
1238 FN_GLOBAL_BOOL(lp_use_rhosts,&Globals.bUseRhosts)
1239 FN_GLOBAL_BOOL(lp_readprediction,&Globals.bReadPrediction)
1240 FN_GLOBAL_BOOL(lp_readbmpx,&Globals.bReadbmpx)
1241 FN_GLOBAL_BOOL(lp_readraw,&Globals.bReadRaw)
1242 FN_GLOBAL_BOOL(lp_writeraw,&Globals.bWriteRaw)
1243 FN_GLOBAL_BOOL(lp_null_passwords,&Globals.bNullPasswords)
1244 FN_GLOBAL_BOOL(lp_strip_dot,&Globals.bStripDot)
1245 FN_GLOBAL_BOOL(lp_encrypted_passwords,&Globals.bEncryptPasswords)
1246 FN_GLOBAL_BOOL(lp_update_encrypted,&Globals.bUpdateEncrypt)
1247 FN_GLOBAL_BOOL(lp_syslog_only,&Globals.bSyslogOnly)
1248 FN_GLOBAL_BOOL(lp_timestamp_logs,&Globals.bTimestampLogs)
1249 FN_GLOBAL_BOOL(lp_browse_list,&Globals.bBrowseList)
1250 FN_GLOBAL_BOOL(lp_unix_realname,&Globals.bUnixRealname)
1251 FN_GLOBAL_BOOL(lp_nis_home_map,&Globals.bNISHomeMap)
1252 static FN_GLOBAL_BOOL(lp_time_server,&Globals.bTimeServer)
1253 FN_GLOBAL_BOOL(lp_bind_interfaces_only,&Globals.bBindInterfacesOnly)
1254 FN_GLOBAL_BOOL(lp_unix_password_sync,&Globals.bUnixPasswdSync)
1255 FN_GLOBAL_BOOL(lp_passwd_chat_debug,&Globals.bPasswdChatDebug)
1256 FN_GLOBAL_BOOL(lp_ole_locking_compat,&Globals.bOleLockingCompat)
1257 FN_GLOBAL_BOOL(lp_nt_smb_support,&Globals.bNTSmbSupport)
1258 FN_GLOBAL_BOOL(lp_nt_pipe_support,&Globals.bNTPipeSupport)
1259 FN_GLOBAL_BOOL(lp_stat_cache,&Globals.bStatCache)
1260
1261 FN_GLOBAL_INTEGER(lp_os_level,&Globals.os_level)
1262 FN_GLOBAL_INTEGER(lp_max_ttl,&Globals.max_ttl)
1263 FN_GLOBAL_INTEGER(lp_max_wins_ttl,&Globals.max_wins_ttl)
1264 FN_GLOBAL_INTEGER(lp_min_wins_ttl,&Globals.max_wins_ttl)
1265 FN_GLOBAL_INTEGER(lp_max_log_size,&Globals.max_log_size)
1266 FN_GLOBAL_INTEGER(lp_max_open_files,&Globals.max_open_files)
1267 FN_GLOBAL_INTEGER(lp_maxxmit,&Globals.max_xmit)
1268 FN_GLOBAL_INTEGER(lp_maxmux,&Globals.max_mux)
1269 FN_GLOBAL_INTEGER(lp_passwordlevel,&Globals.pwordlevel)
1270 FN_GLOBAL_INTEGER(lp_usernamelevel,&Globals.unamelevel)
1271 FN_GLOBAL_INTEGER(lp_readsize,&Globals.ReadSize)
1272 FN_GLOBAL_INTEGER(lp_shmem_size,&Globals.shmem_size)
1273 FN_GLOBAL_INTEGER(lp_deadtime,&Globals.deadtime)
1274 FN_GLOBAL_INTEGER(lp_maxprotocol,&Globals.maxprotocol)
1275 FN_GLOBAL_INTEGER(lp_security,&Globals.security)
1276 FN_GLOBAL_INTEGER(lp_maxdisksize,&Globals.maxdisksize)
1277 FN_GLOBAL_INTEGER(lp_lpqcachetime,&Globals.lpqcachetime)
1278 FN_GLOBAL_INTEGER(lp_syslog,&Globals.syslog)
1279 FN_GLOBAL_INTEGER(lp_client_code_page,&Globals.client_code_page)
1280 static FN_GLOBAL_INTEGER(lp_announce_as,&Globals.announce_as)
1281 FN_GLOBAL_INTEGER(lp_lm_announce,&Globals.lm_announce)
1282 FN_GLOBAL_INTEGER(lp_lm_interval,&Globals.lm_interval)
1283 FN_GLOBAL_INTEGER(lp_machine_password_timeout,&Globals.machine_password_timeout)
1284 FN_GLOBAL_INTEGER(lp_change_notify_timeout,&Globals.change_notify_timeout)
1285 FN_GLOBAL_INTEGER(lp_stat_cache_size,&Globals.stat_cache_size)
1286 FN_GLOBAL_INTEGER(lp_map_to_guest,&Globals.map_to_guest)
1287
1288 #ifdef WITH_LDAP
1289 FN_GLOBAL_INTEGER(lp_ldap_port,&Globals.ldap_port)
1290 #endif /* WITH_LDAP */
1291
1292 FN_LOCAL_STRING(lp_preexec,szPreExec)
1293 FN_LOCAL_STRING(lp_postexec,szPostExec)
1294 FN_LOCAL_STRING(lp_rootpreexec,szRootPreExec)
1295 FN_LOCAL_STRING(lp_rootpostexec,szRootPostExec)
1296 FN_LOCAL_STRING(lp_servicename,szService)
1297 FN_LOCAL_STRING(lp_pathname,szPath)
1298 FN_LOCAL_STRING(lp_dontdescend,szDontdescend)
1299 FN_LOCAL_STRING(lp_username,szUsername)
1300 FN_LOCAL_STRING(lp_guestaccount,szGuestaccount)
1301 FN_LOCAL_STRING(lp_invalid_users,szInvalidUsers)
1302 FN_LOCAL_STRING(lp_valid_users,szValidUsers)
1303 FN_LOCAL_STRING(lp_admin_users,szAdminUsers)
1304 FN_LOCAL_STRING(lp_printcommand,szPrintcommand)
1305 FN_LOCAL_STRING(lp_lpqcommand,szLpqcommand)
1306 FN_LOCAL_STRING(lp_lprmcommand,szLprmcommand)
1307 FN_LOCAL_STRING(lp_lppausecommand,szLppausecommand)
1308 FN_LOCAL_STRING(lp_lpresumecommand,szLpresumecommand)
1309 FN_LOCAL_STRING(lp_queuepausecommand,szQueuepausecommand)
1310 FN_LOCAL_STRING(lp_queueresumecommand,szQueueresumecommand)
1311 FN_LOCAL_STRING(lp_printername,szPrintername)
1312 FN_LOCAL_STRING(lp_printerdriver,szPrinterDriver)
1313 FN_LOCAL_STRING(lp_hostsallow,szHostsallow)
1314 FN_LOCAL_STRING(lp_hostsdeny,szHostsdeny)
1315 FN_LOCAL_STRING(lp_magicscript,szMagicScript)
1316 FN_LOCAL_STRING(lp_magicoutput,szMagicOutput)
1317 FN_LOCAL_STRING(lp_comment,comment)
1318 FN_LOCAL_STRING(lp_force_user,force_user)
1319 FN_LOCAL_STRING(lp_force_group,force_group)
1320 FN_LOCAL_STRING(lp_readlist,readlist)
1321 FN_LOCAL_STRING(lp_writelist,writelist)
1322 FN_LOCAL_STRING(lp_fstype,fstype)
1323 FN_LOCAL_STRING(lp_vfsobj,vfsObjectFile)
1324 static FN_LOCAL_STRING(lp_volume,volume)
1325 FN_LOCAL_STRING(lp_mangled_map,szMangledMap)
1326 FN_LOCAL_STRING(lp_veto_files,szVetoFiles)
1327 FN_LOCAL_STRING(lp_hide_files,szHideFiles)
1328 FN_LOCAL_STRING(lp_veto_oplocks,szVetoOplockFiles)
1329 FN_LOCAL_STRING(lp_driverlocation,szPrinterDriverLocation)
1330
1331 FN_LOCAL_BOOL(lp_revalidate,bRevalidate)
1332 FN_LOCAL_BOOL(lp_casesensitive,bCaseSensitive)
1333 FN_LOCAL_BOOL(lp_preservecase,bCasePreserve)
1334 FN_LOCAL_BOOL(lp_shortpreservecase,bShortCasePreserve)
1335 FN_LOCAL_BOOL(lp_casemangle,bCaseMangle)
1336 FN_LOCAL_BOOL(lp_status,status)
1337 FN_LOCAL_BOOL(lp_hide_dot_files,bHideDotFiles)
1338 FN_LOCAL_BOOL(lp_browseable,bBrowseable)
1339 FN_LOCAL_BOOL(lp_readonly,bRead_only)
1340 FN_LOCAL_BOOL(lp_no_set_dir,bNo_set_dir)
1341 FN_LOCAL_BOOL(lp_guest_ok,bGuest_ok)
1342 FN_LOCAL_BOOL(lp_guest_only,bGuest_only)
1343 FN_LOCAL_BOOL(lp_print_ok,bPrint_ok)
1344 FN_LOCAL_BOOL(lp_postscript,bPostscript)
1345 FN_LOCAL_BOOL(lp_map_hidden,bMap_hidden)
1346 FN_LOCAL_BOOL(lp_map_archive,bMap_archive)
1347 FN_LOCAL_BOOL(lp_locking,bLocking)
1348 FN_LOCAL_BOOL(lp_strict_locking,bStrictLocking)
1349 FN_LOCAL_BOOL(lp_share_modes,bShareModes)
1350 FN_LOCAL_BOOL(lp_oplocks,bOpLocks)
1351 FN_LOCAL_BOOL(lp_onlyuser,bOnlyUser)
1352 FN_LOCAL_BOOL(lp_manglednames,bMangledNames)
1353 FN_LOCAL_BOOL(lp_widelinks,bWidelinks)
1354 FN_LOCAL_BOOL(lp_symlinks,bSymlinks)
1355 FN_LOCAL_BOOL(lp_syncalways,bSyncAlways)
1356 FN_LOCAL_BOOL(lp_strict_sync,bStrictSync)
1357 FN_LOCAL_BOOL(lp_map_system,bMap_system)
1358 FN_LOCAL_BOOL(lp_delete_readonly,bDeleteReadonly)
1359 FN_LOCAL_BOOL(lp_fake_oplocks,bFakeOplocks)
1360 FN_LOCAL_BOOL(lp_recursive_veto_delete,bDeleteVetoFiles)
1361 FN_LOCAL_BOOL(lp_dos_filetimes,bDosFiletimes)
1362 FN_LOCAL_BOOL(lp_dos_filetime_resolution,bDosFiletimeResolution)
1363 FN_LOCAL_BOOL(lp_fake_dir_create_times,bFakeDirCreateTimes)
1364 FN_LOCAL_BOOL(lp_blocking_locks,bBlockingLocks)
1365
1366 FN_LOCAL_INTEGER(lp_create_mode,iCreate_mask)
1367 FN_LOCAL_INTEGER(lp_force_create_mode,iCreate_force_mode)
1368 FN_LOCAL_INTEGER(lp_dir_mode,iDir_mask)
1369 FN_LOCAL_INTEGER(lp_force_dir_mode,iDir_force_mode)
1370 FN_LOCAL_INTEGER(lp_max_connections,iMaxConnections)
1371 FN_LOCAL_INTEGER(lp_defaultcase,iDefaultCase)
1372 FN_LOCAL_INTEGER(lp_minprintspace,iMinPrintSpace)
1373 FN_LOCAL_INTEGER(lp_printing,iPrinting)
1374
1375 FN_LOCAL_CHAR(lp_magicchar,magic_char)
1376
1377 #if defined(HAVE_MYSQL_H) && defined(WITH_MYSQLSAM)
1378 FN_GLOBAL_STRING(lp_mysql_host,&Globals.sMysqlHost)
1379 FN_GLOBAL_STRING(lp_mysql_user,&Globals.sMysqlUser)
1380 FN_GLOBAL_STRING(lp_mysql_passfile,&Globals.sMysqlPassFile)
1381 FN_GLOBAL_STRING(lp_mysql_db,&Globals.sMysqlDatabase)
1382 FN_GLOBAL_STRING(lp_mysql_table,&Globals.sMysqlTable)
1383 #endif
1384
1385
1386 /* local prototypes */
1387 static int    strwicmp( char *psz1, char *psz2 );
1388 static int    map_parameter( char *pszParmName);
1389 static BOOL   set_boolean( BOOL *pb, char *pszParmValue );
1390 static int    getservicebyname(char *pszServiceName, service *pserviceDest);
1391 static void   copy_service( service *pserviceDest, 
1392                             service *pserviceSource,
1393                             BOOL *pcopymapDest );
1394 static BOOL   service_ok(int iService);
1395 static BOOL   do_parameter(char *pszParmName, char *pszParmValue);
1396 static BOOL   do_section(char *pszSectionName);
1397 static void init_copymap(service *pservice);
1398
1399
1400 /***************************************************************************
1401 initialise a service to the defaults
1402 ***************************************************************************/
1403 static void init_service(service *pservice)
1404 {
1405   bzero((char *)pservice,sizeof(service));
1406   copy_service(pservice,&sDefault,NULL);
1407 }
1408
1409
1410 /***************************************************************************
1411 free the dynamically allocated parts of a service struct
1412 ***************************************************************************/
1413 static void free_service(service *pservice)
1414 {
1415   int i;
1416   if (!pservice)
1417      return;
1418
1419   if(pservice->szService)
1420     DEBUG(5,("free_service: Freeing service %s\n", pservice->szService));
1421
1422   string_free(&pservice->szService);
1423   if (pservice->copymap)
1424   {
1425     free(pservice->copymap);
1426     pservice->copymap = NULL;
1427   }
1428  
1429   for (i=0;parm_table[i].label;i++)
1430     if ((parm_table[i].type == P_STRING ||
1431          parm_table[i].type == P_USTRING) &&
1432         parm_table[i].class == P_LOCAL)
1433       string_free((char **)(((char *)pservice) + PTR_DIFF(parm_table[i].ptr,&sDefault)));
1434 }
1435
1436 /***************************************************************************
1437 add a new service to the services array initialising it with the given 
1438 service
1439 ***************************************************************************/
1440 static int add_a_service(service *pservice, char *name)
1441 {
1442   int i;
1443   service tservice;
1444   int num_to_alloc = iNumServices+1;
1445
1446   tservice = *pservice;
1447
1448   /* it might already exist */
1449   if (name) 
1450     {
1451       i = getservicebyname(name,NULL);
1452       if (i >= 0)
1453         return(i);
1454     }
1455
1456   /* find an invalid one */
1457   for (i=0;i<iNumServices;i++)
1458     if (!pSERVICE(i)->valid)
1459       break;
1460
1461   /* if not, then create one */
1462   if (i == iNumServices)
1463     {
1464       ServicePtrs = (service **)Realloc(ServicePtrs,sizeof(service *)*num_to_alloc);
1465       if (ServicePtrs)
1466         pSERVICE(iNumServices) = (service *)malloc(sizeof(service));
1467
1468       if (!ServicePtrs || !pSERVICE(iNumServices))
1469         return(-1);
1470
1471       iNumServices++;
1472     }
1473   else
1474     free_service(pSERVICE(i));
1475
1476   pSERVICE(i)->valid = True;
1477
1478   init_service(pSERVICE(i));
1479   copy_service(pSERVICE(i),&tservice,NULL);
1480   if (name)
1481     string_set(&iSERVICE(i).szService,name);  
1482
1483   return(i);
1484 }
1485
1486 /***************************************************************************
1487 add a new home service, with the specified home directory, defaults coming 
1488 from service ifrom
1489 ***************************************************************************/
1490 BOOL lp_add_home(char *pszHomename, int iDefaultService, char *pszHomedir)
1491 {
1492   int i = add_a_service(pSERVICE(iDefaultService),pszHomename);
1493
1494   if (i < 0)
1495     return(False);
1496
1497   if (!(*(iSERVICE(i).szPath)) || strequal(iSERVICE(i).szPath,lp_pathname(-1)))
1498     string_set(&iSERVICE(i).szPath,pszHomedir);
1499   if (!(*(iSERVICE(i).comment)))
1500     {
1501       pstring comment;
1502       slprintf(comment,sizeof(comment)-1,
1503                "Home directory of %s",pszHomename);
1504       string_set(&iSERVICE(i).comment,comment);
1505     }
1506   iSERVICE(i).bAvailable = sDefault.bAvailable;
1507   iSERVICE(i).bBrowseable = sDefault.bBrowseable;
1508
1509   DEBUG(3,("adding home directory %s at %s\n", pszHomename, pszHomedir));
1510
1511   return(True);
1512 }
1513
1514 /***************************************************************************
1515 add a new service, based on an old one
1516 ***************************************************************************/
1517 int lp_add_service(char *pszService, int iDefaultService)
1518 {
1519   return(add_a_service(pSERVICE(iDefaultService),pszService));
1520 }
1521
1522
1523 /***************************************************************************
1524 add the IPC service
1525 ***************************************************************************/
1526 static BOOL lp_add_ipc(void)
1527 {
1528   pstring comment;
1529   int i = add_a_service(&sDefault,"IPC$");
1530
1531   if (i < 0)
1532     return(False);
1533
1534   slprintf(comment,sizeof(comment)-1,
1535            "IPC Service (%s)", Globals.szServerString );
1536
1537   string_set(&iSERVICE(i).szPath,tmpdir());
1538   string_set(&iSERVICE(i).szUsername,"");
1539   string_set(&iSERVICE(i).comment,comment);
1540   string_set(&iSERVICE(i).fstype,"IPC");
1541   iSERVICE(i).status = False;
1542   iSERVICE(i).iMaxConnections = 0;
1543   iSERVICE(i).bAvailable = True;
1544   iSERVICE(i).bRead_only = True;
1545   iSERVICE(i).bGuest_only = False;
1546   iSERVICE(i).bGuest_ok = True;
1547   iSERVICE(i).bPrint_ok = False;
1548   iSERVICE(i).bBrowseable = sDefault.bBrowseable;
1549
1550   DEBUG(3,("adding IPC service\n"));
1551
1552   return(True);
1553 }
1554
1555
1556 /***************************************************************************
1557 add a new printer service, with defaults coming from service iFrom
1558 ***************************************************************************/
1559 BOOL lp_add_printer(char *pszPrintername, int iDefaultService)
1560 {
1561   char *comment = "From Printcap";
1562   int i = add_a_service(pSERVICE(iDefaultService),pszPrintername);
1563   
1564   if (i < 0)
1565     return(False);
1566   
1567   /* note that we do NOT default the availability flag to True - */
1568   /* we take it from the default service passed. This allows all */
1569   /* dynamic printers to be disabled by disabling the [printers] */
1570   /* entry (if/when the 'available' keyword is implemented!).    */
1571   
1572   /* the printer name is set to the service name. */
1573   string_set(&iSERVICE(i).szPrintername,pszPrintername);
1574   string_set(&iSERVICE(i).comment,comment);
1575   iSERVICE(i).bBrowseable = sDefault.bBrowseable;
1576   /* Printers cannot be read_only. */
1577   iSERVICE(i).bRead_only = False;
1578   /* No share modes on printer services. */
1579   iSERVICE(i).bShareModes = False;
1580   /* No oplocks on printer services. */
1581   iSERVICE(i).bOpLocks = False;
1582   /* Printer services must be printable. */
1583   iSERVICE(i).bPrint_ok = True;
1584   
1585   DEBUG(3,("adding printer service %s\n",pszPrintername));
1586   
1587   return(True);
1588 }
1589
1590
1591 /***************************************************************************
1592 Do a case-insensitive, whitespace-ignoring string compare.
1593 ***************************************************************************/
1594 static int strwicmp(char *psz1, char *psz2)
1595 {
1596    /* if BOTH strings are NULL, return TRUE, if ONE is NULL return */
1597    /* appropriate value. */
1598    if (psz1 == psz2)
1599       return (0);
1600    else
1601       if (psz1 == NULL)
1602          return (-1);
1603       else
1604           if (psz2 == NULL)
1605               return (1);
1606
1607    /* sync the strings on first non-whitespace */
1608    while (1)
1609    {
1610       while (isspace(*psz1))
1611          psz1++;
1612       while (isspace(*psz2))
1613          psz2++;
1614       if (toupper(*psz1) != toupper(*psz2) || *psz1 == '\0' || *psz2 == '\0')
1615          break;
1616       psz1++;
1617       psz2++;
1618    }
1619    return (*psz1 - *psz2);
1620 }
1621
1622 /***************************************************************************
1623 Map a parameter's string representation to something we can use. 
1624 Returns False if the parameter string is not recognised, else TRUE.
1625 ***************************************************************************/
1626 static int map_parameter(char *pszParmName)
1627 {
1628    int iIndex;
1629
1630    if (*pszParmName == '-')
1631      return(-1);
1632
1633    for (iIndex = 0; parm_table[iIndex].label; iIndex++) 
1634       if (strwicmp(parm_table[iIndex].label, pszParmName) == 0)
1635          return(iIndex);
1636
1637    DEBUG(0,( "Unknown parameter encountered: \"%s\"\n", pszParmName));
1638    return(-1);
1639 }
1640
1641
1642 /***************************************************************************
1643 Set a boolean variable from the text value stored in the passed string.
1644 Returns True in success, False if the passed string does not correctly 
1645 represent a boolean.
1646 ***************************************************************************/
1647 static BOOL set_boolean(BOOL *pb, char *pszParmValue)
1648 {
1649    BOOL bRetval;
1650
1651    bRetval = True;
1652    if (strwicmp(pszParmValue, "yes") == 0 ||
1653        strwicmp(pszParmValue, "true") == 0 ||
1654        strwicmp(pszParmValue, "1") == 0)
1655       *pb = True;
1656    else
1657       if (strwicmp(pszParmValue, "no") == 0 ||
1658           strwicmp(pszParmValue, "False") == 0 ||
1659           strwicmp(pszParmValue, "0") == 0)
1660          *pb = False;
1661       else
1662       {
1663          DEBUG(0,("ERROR: Badly formed boolean in configuration file: \"%s\".\n",
1664                pszParmValue));
1665          bRetval = False;
1666       }
1667    return (bRetval);
1668 }
1669
1670 /***************************************************************************
1671 Find a service by name. Otherwise works like get_service.
1672 ***************************************************************************/
1673 static int getservicebyname(char *pszServiceName, service *pserviceDest)
1674 {
1675    int iService;
1676
1677    for (iService = iNumServices - 1; iService >= 0; iService--)
1678       if (VALID(iService) &&
1679           strwicmp(iSERVICE(iService).szService, pszServiceName) == 0) 
1680       {
1681          if (pserviceDest != NULL)
1682            copy_service(pserviceDest, pSERVICE(iService), NULL);
1683          break;
1684       }
1685
1686    return (iService);
1687 }
1688
1689
1690
1691 /***************************************************************************
1692 Copy a service structure to another
1693
1694 If pcopymapDest is NULL then copy all fields
1695 ***************************************************************************/
1696 static void copy_service(service *pserviceDest, 
1697                          service *pserviceSource,
1698                          BOOL *pcopymapDest)
1699 {
1700   int i;
1701   BOOL bcopyall = (pcopymapDest == NULL);
1702
1703   for (i=0;parm_table[i].label;i++)
1704     if (parm_table[i].ptr && parm_table[i].class == P_LOCAL && 
1705         (bcopyall || pcopymapDest[i]))
1706       {
1707         void *def_ptr = parm_table[i].ptr;
1708         void *src_ptr = 
1709           ((char *)pserviceSource) + PTR_DIFF(def_ptr,&sDefault);
1710         void *dest_ptr = 
1711           ((char *)pserviceDest) + PTR_DIFF(def_ptr,&sDefault);
1712
1713         switch (parm_table[i].type)
1714           {
1715           case P_BOOL:
1716           case P_BOOLREV:
1717             *(BOOL *)dest_ptr = *(BOOL *)src_ptr;
1718             break;
1719
1720           case P_INTEGER:
1721           case P_ENUM:
1722           case P_OCTAL:
1723             *(int *)dest_ptr = *(int *)src_ptr;
1724             break;
1725
1726           case P_CHAR:
1727             *(char *)dest_ptr = *(char *)src_ptr;
1728             break;
1729
1730           case P_STRING:
1731             string_set(dest_ptr,*(char **)src_ptr);
1732             break;
1733
1734           case P_USTRING:
1735             string_set(dest_ptr,*(char **)src_ptr);
1736             strupper(*(char **)dest_ptr);
1737             break;
1738           default:
1739             break;
1740           }
1741       }
1742
1743   if (bcopyall)
1744     {
1745       init_copymap(pserviceDest);
1746       if (pserviceSource->copymap)
1747         memcpy((void *)pserviceDest->copymap,
1748                (void *)pserviceSource->copymap,sizeof(BOOL)*NUMPARAMETERS);
1749     }
1750 }
1751
1752 /***************************************************************************
1753 Check a service for consistency. Return False if the service is in any way
1754 incomplete or faulty, else True.
1755 ***************************************************************************/
1756 static BOOL service_ok(int iService)
1757 {
1758    BOOL bRetval;
1759
1760    bRetval = True;
1761    if (iSERVICE(iService).szService[0] == '\0')
1762    {
1763       DEBUG(0,( "The following message indicates an internal error:\n"));
1764       DEBUG(0,( "No service name in service entry.\n"));
1765       bRetval = False;
1766    }
1767
1768    /* The [printers] entry MUST be printable. I'm all for flexibility, but */
1769    /* I can't see why you'd want a non-printable printer service...        */
1770    if (strwicmp(iSERVICE(iService).szService,PRINTERS_NAME) == 0)
1771       if (!iSERVICE(iService).bPrint_ok)
1772       {
1773          DEBUG(0,( "WARNING: [%s] service MUST be printable!\n",
1774                iSERVICE(iService).szService));
1775          iSERVICE(iService).bPrint_ok = True;
1776       }
1777
1778    if (iSERVICE(iService).szPath[0] == '\0' &&
1779        strwicmp(iSERVICE(iService).szService,HOMES_NAME) != 0)
1780    {
1781       DEBUG(0,("No path in service %s - using %s\n",iSERVICE(iService).szService,tmpdir()));
1782       string_set(&iSERVICE(iService).szPath,tmpdir());      
1783    }
1784
1785    /* If a service is flagged unavailable, log the fact at level 0. */
1786    if (!iSERVICE(iService).bAvailable) 
1787       DEBUG(1,( "NOTE: Service %s is flagged unavailable.\n",
1788             iSERVICE(iService).szService));
1789
1790    return (bRetval);
1791 }
1792
1793 static struct file_lists {
1794   struct file_lists *next;
1795   char *name;
1796   time_t modtime;
1797 } *file_lists = NULL;
1798
1799 /*******************************************************************
1800 keep a linked list of all config files so we know when one has changed 
1801 it's date and needs to be reloaded
1802 ********************************************************************/
1803 static void add_to_file_list(char *fname)
1804 {
1805   struct file_lists *f=file_lists;
1806
1807   while (f) {
1808     if (f->name && !strcmp(f->name,fname)) break;
1809     f = f->next;
1810   }
1811
1812   if (!f) {
1813     f = (struct file_lists *)malloc(sizeof(file_lists[0]));
1814     if (!f) return;
1815     f->next = file_lists;
1816     f->name = strdup(fname);
1817     if (!f->name) {
1818       free(f);
1819       return;
1820     }
1821     file_lists = f;
1822   }
1823
1824   {
1825     pstring n2;
1826     pstrcpy(n2,fname);
1827     standard_sub_basic(n2);
1828     f->modtime = file_modtime(n2);
1829   }
1830
1831 }
1832
1833 /*******************************************************************
1834 check if a config file has changed date
1835 ********************************************************************/
1836 BOOL lp_file_list_changed(void)
1837 {
1838   struct file_lists *f = file_lists;
1839   DEBUG(6,("lp_file_list_changed()\n"));
1840
1841   while (f)
1842   {
1843     pstring n2;
1844     time_t mod_time;
1845
1846     pstrcpy(n2,f->name);
1847     standard_sub_basic(n2);
1848
1849     DEBUGADD( 6, ( "file %s -> %s  last mod_time: %s\n",
1850                    f->name, n2, ctime(&f->modtime) ) );
1851
1852     mod_time = file_modtime(n2);
1853
1854     if (f->modtime != mod_time) {
1855             DEBUGADD(6,("file %s modified: %s\n", n2, ctime(&mod_time)));
1856             f->modtime = mod_time;
1857             return(True);
1858     }
1859     f = f->next;
1860   }
1861   return(False);
1862 }
1863
1864 /***************************************************************************
1865   handle the interpretation of the vfs object parameter
1866   *************************************************************************/
1867 static BOOL handle_vfs_object(char *pszParmValue,char **ptr)
1868 {
1869     /* Set string value */
1870
1871     string_set(ptr,pszParmValue);
1872
1873     /* Do any other initialisation required for vfs.  Note that
1874        anything done here may have linking repercussions in nmbd. */
1875
1876     return True;
1877 }
1878
1879 /***************************************************************************
1880   handle the interpretation of the coding system parameter
1881   *************************************************************************/
1882 static BOOL handle_coding_system(char *pszParmValue,char **ptr)
1883 {
1884         string_set(ptr,pszParmValue);
1885         interpret_coding_system(pszParmValue);
1886         return(True);
1887 }
1888
1889 /***************************************************************************
1890 handle the interpretation of the character set system parameter
1891 ***************************************************************************/
1892 static BOOL handle_character_set(char *pszParmValue,char **ptr)
1893 {
1894         string_set(ptr,pszParmValue);
1895         interpret_character_set(pszParmValue);
1896         return(True);
1897 }
1898
1899
1900 /***************************************************************************
1901 handle the valid chars lines
1902 ***************************************************************************/
1903 static BOOL handle_valid_chars(char *pszParmValue,char **ptr)
1904
1905   string_set(ptr,pszParmValue);
1906
1907   /* A dependency here is that the parameter client code page must be
1908      set before this is called - as calling codepage_initialise()
1909      would overwrite the valid char lines.
1910    */
1911   codepage_initialise(lp_client_code_page());
1912
1913   add_char_string(pszParmValue);
1914   return(True);
1915 }
1916
1917
1918 /***************************************************************************
1919 handle the include operation
1920 ***************************************************************************/
1921 static BOOL handle_include(char *pszParmValue,char **ptr)
1922
1923   pstring fname;
1924   pstrcpy(fname,pszParmValue);
1925
1926   add_to_file_list(fname);
1927
1928   standard_sub_basic(fname);
1929
1930   string_set(ptr,fname);
1931
1932   if (file_exist(fname,NULL))
1933     return(pm_process(fname, do_section, do_parameter));      
1934
1935   DEBUG(2,("Can't find include file %s\n",fname));
1936
1937   return(False);
1938 }
1939
1940
1941 /***************************************************************************
1942 handle the interpretation of the copy parameter
1943 ***************************************************************************/
1944 static BOOL handle_copy(char *pszParmValue,char **ptr)
1945 {
1946    BOOL bRetval;
1947    int iTemp;
1948    service serviceTemp;
1949
1950    string_set(ptr,pszParmValue);
1951
1952    init_service(&serviceTemp);
1953
1954    bRetval = False;
1955    
1956    DEBUG(3,("Copying service from service %s\n",pszParmValue));
1957
1958    if ((iTemp = getservicebyname(pszParmValue, &serviceTemp)) >= 0)
1959      {
1960        if (iTemp == iServiceIndex)
1961          {
1962            DEBUG(0,("Can't copy service %s - unable to copy self!\n",
1963                     pszParmValue));
1964          }
1965        else
1966          {
1967            copy_service(pSERVICE(iServiceIndex), 
1968                         &serviceTemp,
1969                         iSERVICE(iServiceIndex).copymap);
1970            bRetval = True;
1971          }
1972      }
1973    else
1974      {
1975        DEBUG(0,( "Unable to copy service - source not found: %s\n",
1976                 pszParmValue));
1977        bRetval = False;
1978      }
1979
1980    free_service(&serviceTemp);
1981    return (bRetval);
1982 }
1983
1984
1985 /***************************************************************************
1986 initialise a copymap
1987 ***************************************************************************/
1988 static void init_copymap(service *pservice)
1989 {
1990   int i;
1991   if (pservice->copymap) free(pservice->copymap);
1992   pservice->copymap = (BOOL *)malloc(sizeof(BOOL)*NUMPARAMETERS);
1993   if (!pservice->copymap)
1994     DEBUG(0,("Couldn't allocate copymap!! (size %d)\n",NUMPARAMETERS));
1995
1996   for (i=0;i<NUMPARAMETERS;i++)
1997     pservice->copymap[i] = True;
1998 }
1999
2000
2001 /***************************************************************************
2002  return the local pointer to a parameter given the service number and the 
2003  pointer into the default structure
2004 ***************************************************************************/
2005 void *lp_local_ptr(int snum, void *ptr)
2006 {
2007         return (void *)(((char *)pSERVICE(snum)) + PTR_DIFF(ptr,&sDefault));
2008 }
2009
2010 /***************************************************************************
2011 Process a parameter for a particular service number. If snum < 0
2012 then assume we are in the globals
2013 ***************************************************************************/
2014 BOOL lp_do_parameter(int snum, char *pszParmName, char *pszParmValue)
2015 {
2016    int parmnum, i;
2017    void *parm_ptr=NULL; /* where we are going to store the result */
2018    void *def_ptr=NULL;
2019
2020    parmnum = map_parameter(pszParmName);
2021
2022    if (parmnum < 0)
2023      {
2024        DEBUG(0,( "Ignoring unknown parameter \"%s\"\n", pszParmName));
2025        return(True);
2026      }
2027
2028    if (parm_table[parmnum].flags & FLAG_DEPRECATED) {
2029            DEBUG(1,("WARNING: The \"%s\"option is deprecated\n",
2030                     pszParmName));
2031    }
2032
2033    def_ptr = parm_table[parmnum].ptr;
2034
2035    /* we might point at a service, the default service or a global */
2036    if (snum < 0) {
2037      parm_ptr = def_ptr;
2038    } else {
2039        if (parm_table[parmnum].class == P_GLOBAL) {
2040            DEBUG(0,( "Global parameter %s found in service section!\n",pszParmName));
2041            return(True);
2042          }
2043        parm_ptr = ((char *)pSERVICE(snum)) + PTR_DIFF(def_ptr,&sDefault);
2044    }
2045
2046    if (snum >= 0) {
2047            if (!iSERVICE(snum).copymap)
2048                    init_copymap(pSERVICE(snum));
2049            
2050            /* this handles the aliases - set the copymap for other entries with
2051               the same data pointer */
2052            for (i=0;parm_table[i].label;i++)
2053                    if (parm_table[i].ptr == parm_table[parmnum].ptr)
2054                            iSERVICE(snum).copymap[i] = False;
2055    }
2056
2057    /* if it is a special case then go ahead */
2058    if (parm_table[parmnum].special) {
2059            parm_table[parmnum].special(pszParmValue,(char **)parm_ptr);
2060            return(True);
2061    }
2062
2063    /* now switch on the type of variable it is */
2064    switch (parm_table[parmnum].type)
2065      {
2066      case P_BOOL:
2067        set_boolean(parm_ptr,pszParmValue);
2068        break;
2069
2070      case P_BOOLREV:
2071        set_boolean(parm_ptr,pszParmValue);
2072        *(BOOL *)parm_ptr = ! *(BOOL *)parm_ptr;
2073        break;
2074
2075      case P_INTEGER:
2076        *(int *)parm_ptr = atoi(pszParmValue);
2077        break;
2078
2079      case P_CHAR:
2080        *(char *)parm_ptr = *pszParmValue;
2081        break;
2082
2083      case P_OCTAL:
2084        sscanf(pszParmValue,"%o",(int *)parm_ptr);
2085        break;
2086
2087      case P_STRING:
2088        string_set(parm_ptr,pszParmValue);
2089        break;
2090
2091      case P_USTRING:
2092        string_set(parm_ptr,pszParmValue);
2093        strupper(*(char **)parm_ptr);
2094        break;
2095
2096      case P_GSTRING:
2097        pstrcpy((char *)parm_ptr,pszParmValue);
2098        break;
2099
2100      case P_UGSTRING:
2101        pstrcpy((char *)parm_ptr,pszParmValue);
2102        strupper((char *)parm_ptr);
2103        break;
2104
2105      case P_ENUM:
2106              for (i=0;parm_table[parmnum].enum_list[i].name;i++) {
2107                      if (strequal(pszParmValue, parm_table[parmnum].enum_list[i].name)) {
2108                              *(int *)parm_ptr = parm_table[parmnum].enum_list[i].value;
2109                              break;
2110                      }
2111              }
2112              break;
2113      case P_SEP:
2114              break;
2115      }
2116
2117    return(True);
2118 }
2119
2120 /***************************************************************************
2121 Process a parameter.
2122 ***************************************************************************/
2123 static BOOL do_parameter( char *pszParmName, char *pszParmValue )
2124 {
2125   if( !bInGlobalSection && bGlobalOnly )
2126     return(True);
2127
2128   DEBUGADD( 3, ( "doing parameter %s = %s\n", pszParmName, pszParmValue ) );
2129
2130   return( lp_do_parameter( bInGlobalSection ? -2 : iServiceIndex,
2131                            pszParmName,
2132                            pszParmValue ) );
2133 }
2134
2135
2136 /***************************************************************************
2137 print a parameter of the specified type
2138 ***************************************************************************/
2139 static void print_parameter(struct parm_struct *p,void *ptr, FILE *f)
2140 {
2141         int i;
2142         switch (p->type) {
2143         case P_ENUM:
2144                 for (i=0;p->enum_list[i].name;i++) {
2145                         if (*(int *)ptr == p->enum_list[i].value) {
2146                                 fprintf(f,"%s",p->enum_list[i].name);
2147                                 break;
2148                         }
2149                 }
2150                 break;
2151
2152         case P_BOOL:
2153                 fprintf(f,"%s",BOOLSTR(*(BOOL *)ptr));
2154                 break;
2155       
2156         case P_BOOLREV:
2157                 fprintf(f,"%s",BOOLSTR(! *(BOOL *)ptr));
2158                 break;
2159       
2160         case P_INTEGER:
2161                 fprintf(f,"%d",*(int *)ptr);
2162                 break;
2163       
2164         case P_CHAR:
2165                 fprintf(f,"%c",*(char *)ptr);
2166                 break;
2167       
2168         case P_OCTAL:
2169                 fprintf(f,"0%o",*(int *)ptr);
2170                 break;
2171       
2172         case P_GSTRING:
2173         case P_UGSTRING:
2174                 if ((char *)ptr)
2175                         fprintf(f,"%s",(char *)ptr);
2176                 break;
2177                 
2178         case P_STRING:
2179         case P_USTRING:
2180                 if (*(char **)ptr)
2181                         fprintf(f,"%s",*(char **)ptr);
2182                 break;
2183         case P_SEP:
2184                 break;
2185         }
2186 }
2187
2188
2189 /***************************************************************************
2190 check if two parameters are equal
2191 ***************************************************************************/
2192 static BOOL equal_parameter(parm_type type,void *ptr1,void *ptr2)
2193 {
2194   switch (type)
2195     {
2196     case P_BOOL:
2197     case P_BOOLREV:
2198       return(*((BOOL *)ptr1) == *((BOOL *)ptr2));
2199
2200     case P_INTEGER:
2201     case P_ENUM:
2202     case P_OCTAL:
2203       return(*((int *)ptr1) == *((int *)ptr2));
2204       
2205     case P_CHAR:
2206       return(*((char *)ptr1) == *((char *)ptr2));
2207
2208     case P_GSTRING:
2209     case P_UGSTRING:
2210       {
2211         char *p1 = (char *)ptr1, *p2 = (char *)ptr2;
2212         if (p1 && !*p1) p1 = NULL;
2213         if (p2 && !*p2) p2 = NULL;
2214         return(p1==p2 || strequal(p1,p2));
2215       }
2216     case P_STRING:
2217     case P_USTRING:
2218       {
2219         char *p1 = *(char **)ptr1, *p2 = *(char **)ptr2;
2220         if (p1 && !*p1) p1 = NULL;
2221         if (p2 && !*p2) p2 = NULL;
2222         return(p1==p2 || strequal(p1,p2));
2223       }
2224      case P_SEP:
2225              break;
2226     }
2227   return(False);
2228 }
2229
2230 /***************************************************************************
2231 Process a new section (service). At this stage all sections are services.
2232 Later we'll have special sections that permit server parameters to be set.
2233 Returns True on success, False on failure.
2234 ***************************************************************************/
2235 static BOOL do_section(char *pszSectionName)
2236 {
2237    BOOL bRetval;
2238    BOOL isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) || 
2239                     (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
2240    bRetval = False;
2241
2242    /* if we were in a global section then do the local inits */
2243    if (bInGlobalSection && !isglobal)
2244      init_locals();
2245
2246    /* if we've just struck a global section, note the fact. */
2247    bInGlobalSection = isglobal;   
2248
2249    /* check for multiple global sections */
2250    if (bInGlobalSection)
2251    {
2252      DEBUG( 3, ( "Processing section \"[%s]\"\n", pszSectionName ) );
2253      return(True);
2254    }
2255
2256    if (!bInGlobalSection && bGlobalOnly) return(True);
2257
2258    /* if we have a current service, tidy it up before moving on */
2259    bRetval = True;
2260
2261    if (iServiceIndex >= 0)
2262      bRetval = service_ok(iServiceIndex);
2263
2264    /* if all is still well, move to the next record in the services array */
2265    if (bRetval)
2266      {
2267        /* We put this here to avoid an odd message order if messages are */
2268        /* issued by the post-processing of a previous section. */
2269        DEBUG(2,( "Processing section \"[%s]\"\n", pszSectionName));
2270
2271        if ((iServiceIndex=add_a_service(&sDefault,pszSectionName)) < 0)
2272          {
2273            DEBUG(0,("Failed to add a new service\n"));
2274            return(False);
2275          }
2276      }
2277
2278    return (bRetval);
2279 }
2280
2281
2282 /***************************************************************************
2283 determine if a partcular base parameter is currently set to the default value.
2284 ***************************************************************************/
2285 static BOOL is_default(int i)
2286 {
2287         if (!defaults_saved) return False;
2288         switch (parm_table[i].type) {
2289         case P_STRING:
2290         case P_USTRING:
2291                 return strequal(parm_table[i].def.svalue,*(char **)parm_table[i].ptr);
2292         case P_GSTRING:
2293         case P_UGSTRING:
2294                 return strequal(parm_table[i].def.svalue,(char *)parm_table[i].ptr);
2295         case P_BOOL:
2296         case P_BOOLREV:
2297                 return parm_table[i].def.bvalue == *(BOOL *)parm_table[i].ptr;
2298         case P_CHAR:
2299                 return parm_table[i].def.cvalue == *(char *)parm_table[i].ptr;
2300         case P_INTEGER:
2301         case P_OCTAL:
2302         case P_ENUM:
2303                 return parm_table[i].def.ivalue == *(int *)parm_table[i].ptr;
2304         case P_SEP:
2305                 break;
2306         }
2307         return False;
2308 }
2309
2310
2311 /***************************************************************************
2312 Display the contents of the global structure.
2313 ***************************************************************************/
2314 static void dump_globals(FILE *f)
2315 {
2316         int i;
2317         fprintf(f, "# Global parameters\n");
2318         
2319         for (i=0;parm_table[i].label;i++)
2320                 if (parm_table[i].class == P_GLOBAL &&
2321                     parm_table[i].ptr &&
2322                     (i == 0 || (parm_table[i].ptr != parm_table[i-1].ptr))) {
2323                         if (defaults_saved && is_default(i)) continue;
2324                         fprintf(f,"\t%s = ",parm_table[i].label);
2325                         print_parameter(&parm_table[i],parm_table[i].ptr, f);
2326                         fprintf(f,"\n");
2327                 }
2328 }
2329
2330 /***************************************************************************
2331 return True if a local parameter is currently set to the global default
2332 ***************************************************************************/
2333 BOOL lp_is_default(int snum, struct parm_struct *parm)
2334 {
2335         int pdiff = PTR_DIFF(parm->ptr,&sDefault);
2336                         
2337         return equal_parameter(parm->type,
2338                                ((char *)pSERVICE(snum)) + pdiff,
2339                                ((char *)&sDefault) + pdiff);
2340 }
2341
2342
2343 /***************************************************************************
2344 Display the contents of a single services record.
2345 ***************************************************************************/
2346 static void dump_a_service(service *pService, FILE *f)
2347 {
2348         int i;
2349         if (pService != &sDefault)
2350                 fprintf(f,"\n[%s]\n",pService->szService);
2351
2352         for (i=0;parm_table[i].label;i++)
2353                 if (parm_table[i].class == P_LOCAL &&
2354                     parm_table[i].ptr && 
2355                     (*parm_table[i].label != '-') &&
2356                     (i == 0 || (parm_table[i].ptr != parm_table[i-1].ptr))) {
2357                         int pdiff = PTR_DIFF(parm_table[i].ptr,&sDefault);
2358                         
2359                         if (pService == &sDefault) {
2360                                 if (defaults_saved && is_default(i)) continue;
2361                         } else {
2362                                 if (equal_parameter(parm_table[i].type,
2363                                                     ((char *)pService) + pdiff,
2364                                                     ((char *)&sDefault) + pdiff)) 
2365                                         continue;
2366                         }
2367
2368                         fprintf(f,"\t%s = ",parm_table[i].label);
2369                         print_parameter(&parm_table[i],
2370                                         ((char *)pService) + pdiff, f);
2371                         fprintf(f,"\n");
2372                 }
2373 }
2374
2375
2376 /***************************************************************************
2377 return info about the next service  in a service. snum==-1 gives the globals
2378
2379 return NULL when out of parameters
2380 ***************************************************************************/
2381 struct parm_struct *lp_next_parameter(int snum, int *i, int allparameters)
2382 {
2383         if (snum == -1) {
2384                 /* do the globals */
2385                 for (;parm_table[*i].label;(*i)++) {
2386                         if (parm_table[*i].class == P_SEPARATOR) 
2387                                 return &parm_table[(*i)++];
2388
2389                         if (!parm_table[*i].ptr || (*parm_table[*i].label == '-'))
2390                                 continue;
2391                         
2392                         if ((*i) > 0 && (parm_table[*i].ptr == parm_table[(*i)-1].ptr))
2393                                 continue;
2394
2395                         return &parm_table[(*i)++];
2396                 }
2397         } else {
2398                 service *pService = pSERVICE(snum);
2399
2400                 for (;parm_table[*i].label;(*i)++) {
2401                         if (parm_table[*i].class == P_SEPARATOR) 
2402                                 return &parm_table[(*i)++];
2403
2404                         if (parm_table[*i].class == P_LOCAL &&
2405                             parm_table[*i].ptr && 
2406                             (*parm_table[*i].label != '-') &&
2407                             ((*i) == 0 || 
2408                              (parm_table[*i].ptr != parm_table[(*i)-1].ptr))) {
2409                                 int pdiff = PTR_DIFF(parm_table[*i].ptr,&sDefault);
2410                                 
2411                                 if (allparameters ||
2412                                     !equal_parameter(parm_table[*i].type,
2413                                                      ((char *)pService) + pdiff,
2414                                                      ((char *)&sDefault) + pdiff)) {
2415                                         return &parm_table[(*i)++];
2416                                 }
2417                         }
2418                 }
2419         }
2420
2421         return NULL;
2422 }
2423
2424
2425 #if 0
2426 /***************************************************************************
2427 Display the contents of a single copy structure.
2428 ***************************************************************************/
2429 static void dump_copy_map(BOOL *pcopymap)
2430 {
2431   int i;
2432   if (!pcopymap) return;
2433
2434   printf("\n\tNon-Copied parameters:\n");
2435
2436   for (i=0;parm_table[i].label;i++)
2437     if (parm_table[i].class == P_LOCAL &&
2438         parm_table[i].ptr && !pcopymap[i] &&
2439         (i == 0 || (parm_table[i].ptr != parm_table[i-1].ptr)))
2440       {
2441         printf("\t\t%s\n",parm_table[i].label);
2442       }
2443 }
2444 #endif
2445
2446 /***************************************************************************
2447 Return TRUE if the passed service number is within range.
2448 ***************************************************************************/
2449 BOOL lp_snum_ok(int iService)
2450 {
2451    return (LP_SNUM_OK(iService) && iSERVICE(iService).bAvailable);
2452 }
2453
2454
2455 /***************************************************************************
2456 auto-load some home services
2457 ***************************************************************************/
2458 static void lp_add_auto_services(char *str)
2459 {
2460         char *s;
2461         char *p;
2462         int homes;
2463
2464         if (!str) return;
2465
2466         s = strdup(str);
2467         if (!s) return;
2468
2469         homes = lp_servicenumber(HOMES_NAME);
2470         
2471         for (p=strtok(s,LIST_SEP);p;p=strtok(NULL,LIST_SEP)) {
2472                 char *home = get_home_dir(p);
2473                 
2474                 if (lp_servicenumber(p) >= 0) continue;
2475                 
2476                 if (home && homes >= 0) {
2477                         lp_add_home(p,homes,home);
2478                 }
2479         }
2480         free(s);
2481 }
2482
2483 /***************************************************************************
2484 auto-load one printer
2485 ***************************************************************************/
2486 void lp_add_one_printer(char *name,char *comment)
2487 {
2488         int printers = lp_servicenumber(PRINTERS_NAME);
2489         int i;
2490
2491         if (lp_servicenumber(name) < 0)  {
2492                 lp_add_printer(name,printers);
2493                 if ((i=lp_servicenumber(name)) >= 0)
2494                         string_set(&iSERVICE(i).comment,comment);
2495         }
2496 }
2497
2498 /***************************************************************************
2499 have we loaded a services file yet?
2500 ***************************************************************************/
2501 BOOL lp_loaded(void)
2502 {
2503   return(bLoaded);
2504 }
2505
2506 /***************************************************************************
2507 unload unused services
2508 ***************************************************************************/
2509 void lp_killunused(BOOL (*snumused)(int ))
2510 {
2511   int i;
2512   for (i=0;i<iNumServices;i++)
2513     if (VALID(i) && (!snumused || !snumused(i)))
2514       {
2515         iSERVICE(i).valid = False;
2516         free_service(pSERVICE(i));
2517       }
2518 }
2519
2520
2521 /***************************************************************************
2522 save the curent values of all global and sDefault parameters into the 
2523 defaults union. This allows swat and testparm to show only the
2524 changed (ie. non-default) parameters.
2525 ***************************************************************************/
2526 static void lp_save_defaults(void)
2527 {
2528         int i;
2529         for (i = 0; parm_table[i].label; i++) {
2530                 if (i>0 && parm_table[i].ptr == parm_table[i-1].ptr) continue;
2531                 switch (parm_table[i].type) {
2532                 case P_STRING:
2533                 case P_USTRING:
2534                         parm_table[i].def.svalue = strdup(*(char **)parm_table[i].ptr);
2535                         break;
2536                 case P_GSTRING:
2537                 case P_UGSTRING:
2538                         parm_table[i].def.svalue = strdup((char *)parm_table[i].ptr);
2539                         break;
2540                 case P_BOOL:
2541                 case P_BOOLREV:
2542                         parm_table[i].def.bvalue = *(BOOL *)parm_table[i].ptr;
2543                         break;
2544                 case P_CHAR:
2545                         parm_table[i].def.cvalue = *(char *)parm_table[i].ptr;
2546                         break;
2547                 case P_INTEGER:
2548                 case P_OCTAL:
2549                 case P_ENUM:
2550                         parm_table[i].def.ivalue = *(int *)parm_table[i].ptr;
2551                         break;
2552                 case P_SEP:
2553                         break;
2554                 }
2555         }
2556         defaults_saved = True;
2557 }
2558
2559
2560 /***************************************************************************
2561 Load the services array from the services file. Return True on success, 
2562 False on failure.
2563 ***************************************************************************/
2564 BOOL lp_load(char *pszFname,BOOL global_only, BOOL save_defaults, BOOL add_ipc)
2565 {
2566   pstring n2;
2567   BOOL bRetval;
2568  
2569   add_to_file_list(pszFname);
2570
2571   bRetval = False;
2572
2573   bInGlobalSection = True;
2574   bGlobalOnly = global_only;
2575   
2576   init_globals();
2577
2578   if (save_defaults) {
2579           init_locals();
2580           lp_save_defaults();
2581   }
2582   
2583   pstrcpy(n2,pszFname);
2584   standard_sub_basic(n2);
2585
2586   /* We get sections first, so have to start 'behind' to make up */
2587   iServiceIndex = -1;
2588   bRetval = pm_process(n2, do_section, do_parameter);
2589   
2590   /* finish up the last section */
2591   DEBUG(3,("pm_process() returned %s\n", BOOLSTR(bRetval)));
2592   if (bRetval)
2593     if (iServiceIndex >= 0)
2594       bRetval = service_ok(iServiceIndex);         
2595
2596   lp_add_auto_services(lp_auto_services());
2597
2598   if (add_ipc)
2599           lp_add_ipc();
2600
2601   set_server_role();
2602   set_default_server_announce_type();
2603
2604   bLoaded = True;
2605
2606   /* Now we check bWINSsupport and set szWINSserver to 127.0.0.1 */
2607   /* if bWINSsupport is true and we are in the client            */
2608
2609   if (in_client && Globals.bWINSsupport) {
2610
2611     string_set(&Globals.szWINSserver, "127.0.0.1");
2612
2613   }
2614
2615   return (bRetval);
2616 }
2617
2618
2619 /***************************************************************************
2620 return the max number of services
2621 ***************************************************************************/
2622 int lp_numservices(void)
2623 {
2624   return(iNumServices);
2625 }
2626
2627 /***************************************************************************
2628 Display the contents of the services array in human-readable form.
2629 ***************************************************************************/
2630 void lp_dump(FILE *f, BOOL show_defaults)
2631 {
2632    int iService;
2633
2634    if (show_defaults) {
2635            defaults_saved = False;
2636    }
2637
2638    dump_globals(f);
2639    
2640    dump_a_service(&sDefault, f);
2641
2642    for (iService = 0; iService < iNumServices; iService++)
2643    {
2644      if (VALID(iService))
2645        {
2646          if (iSERVICE(iService).szService[0] == '\0')
2647            break;
2648          dump_a_service(pSERVICE(iService), f);
2649        }
2650    }
2651 }
2652
2653
2654 /***************************************************************************
2655 Return the number of the service with the given name, or -1 if it doesn't
2656 exist. Note that this is a DIFFERENT ANIMAL from the internal function
2657 getservicebyname()! This works ONLY if all services have been loaded, and
2658 does not copy the found service.
2659 ***************************************************************************/
2660 int lp_servicenumber(char *pszServiceName)
2661 {
2662    int iService;
2663
2664    for (iService = iNumServices - 1; iService >= 0; iService--)
2665       if (VALID(iService) &&
2666           strequal(lp_servicename(iService), pszServiceName)) 
2667          break;
2668
2669    if (iService < 0)
2670      DEBUG(7,("lp_servicenumber: couldn't find %s\n",pszServiceName));
2671    
2672    return (iService);
2673 }
2674
2675 /*******************************************************************
2676   a useful volume label function
2677   ******************************************************************/
2678 char *volume_label(int snum)
2679 {
2680   char *ret = lp_volume(snum);
2681   if (!*ret) return(lp_servicename(snum));
2682   return(ret);
2683 }
2684
2685
2686 /*******************************************************************
2687  Set the server type we will announce as via nmbd.
2688 ********************************************************************/
2689 static void set_server_role(void)
2690 {
2691         server_role = ROLE_DOMAIN_NONE;
2692
2693         switch (lp_security())
2694         {
2695                 case SEC_SHARE:
2696                 {
2697                         if (lp_domain_logons())
2698                         {
2699                                 DEBUG(0,("Server's Role (logon server) conflicts with share-level security\n"));
2700                         }
2701                         break;
2702                 }
2703                 case SEC_SERVER:
2704                 case SEC_DOMAIN:
2705                 {
2706                         if (lp_domain_logons())
2707                         {
2708                                 server_role = ROLE_DOMAIN_BDC;
2709                                 break;
2710                         }
2711                         server_role = ROLE_DOMAIN_MEMBER;
2712                         break;
2713                 }
2714                 case SEC_USER:
2715                 {
2716                         if (lp_domain_logons())
2717                         {
2718                                 server_role = ROLE_DOMAIN_PDC;
2719                                 break;
2720                         }
2721                         break;
2722                 }
2723                 default:
2724                 {
2725                         DEBUG(0,("Server's Role undefined due to unknown security mode\n"));
2726                 }
2727         }
2728 }
2729
2730 /*******************************************************************
2731  Set the server type we will announce as via nmbd.
2732 ********************************************************************/
2733 static void set_default_server_announce_type(void)
2734 {
2735         default_server_announce = 0;
2736         default_server_announce |= SV_TYPE_WORKSTATION;
2737         default_server_announce |= SV_TYPE_SERVER;
2738         default_server_announce |= SV_TYPE_SERVER_UNIX;
2739         default_server_announce |= SV_TYPE_PRINTQ_SERVER;
2740
2741         switch (lp_announce_as())
2742         {
2743                 case ANNOUNCE_AS_NT:
2744                 {
2745                         default_server_announce |= SV_TYPE_SERVER_NT;
2746                         default_server_announce |= SV_TYPE_NT;
2747                         break;
2748                 }
2749                 case ANNOUNCE_AS_WIN95:
2750                 {
2751                         default_server_announce |= SV_TYPE_WIN95_PLUS;
2752                         break;
2753                 }
2754                 case ANNOUNCE_AS_WFW:
2755                 {
2756                         default_server_announce |= SV_TYPE_WFW;
2757                         break;
2758                 }
2759                 default:
2760                 {
2761                         break;
2762                 }
2763         }
2764
2765         switch (lp_server_role())
2766         {
2767                 case ROLE_DOMAIN_MEMBER:
2768                 {
2769                         default_server_announce |= SV_TYPE_DOMAIN_MEMBER;
2770                         break;
2771                 }
2772                 case ROLE_DOMAIN_PDC:
2773                 {
2774                         default_server_announce |= SV_TYPE_DOMAIN_CTRL;
2775                         break;
2776                 }
2777                 case ROLE_DOMAIN_BDC:
2778                 {
2779                         default_server_announce |= SV_TYPE_DOMAIN_BAKCTRL;
2780                         break;
2781                 }
2782                 case ROLE_DOMAIN_NONE:
2783                 default:
2784                 {
2785                         break;
2786                 }
2787         }
2788
2789         if (lp_time_server())
2790         {
2791                 default_server_announce |= SV_TYPE_TIME_SOURCE;
2792         }
2793 }
2794
2795
2796 /*******************************************************************
2797 remove a service
2798 ********************************************************************/
2799 void lp_remove_service(int snum)
2800 {
2801         pSERVICE(snum)->valid = False;
2802 }
2803
2804 /*******************************************************************
2805 copy a service
2806 ********************************************************************/
2807 void lp_copy_service(int snum, char *new_name)
2808 {
2809         char *oldname = lp_servicename(snum);
2810         do_section(new_name);
2811         if (snum >= 0) {
2812                 snum = lp_servicenumber(new_name);
2813                 if (snum >= 0)
2814                         lp_do_parameter(snum, "copy", oldname);
2815         }
2816 }
2817
2818
2819 /*******************************************************************
2820  Get the default server type we will announce as via nmbd.
2821 ********************************************************************/
2822 int lp_default_server_announce(void)
2823 {
2824   return default_server_announce;
2825 }
2826
2827 /*******************************************************************
2828  Split the announce version into major and minor numbers.
2829 ********************************************************************/
2830 int lp_major_announce_version(void)
2831 {
2832   static BOOL got_major = False;
2833   static int major_version = DEFAULT_MAJOR_VERSION;
2834   char *vers;
2835   char *p;
2836
2837   if(got_major)
2838     return major_version;
2839
2840   got_major = True;
2841   if((vers = lp_announce_version()) == NULL)
2842     return major_version;
2843   
2844   if((p = strchr(vers, '.')) == 0)
2845     return major_version;
2846
2847   *p = '\0';
2848   major_version = atoi(vers);
2849   return major_version;
2850 }
2851
2852 int lp_minor_announce_version(void)
2853 {
2854   static BOOL got_minor = False;
2855   static int minor_version = DEFAULT_MINOR_VERSION;
2856   char *vers;
2857   char *p;
2858
2859   if(got_minor)
2860     return minor_version;
2861
2862   got_minor = True;
2863   if((vers = lp_announce_version()) == NULL)
2864     return minor_version;
2865   
2866   if((p = strchr(vers, '.')) == 0)              
2867     return minor_version;
2868     
2869   p++;
2870   minor_version = atoi(p);
2871   return minor_version;
2872 }  
2873
2874 /***********************************************************
2875  Set the global name resolution order (used in smbclient).
2876 ************************************************************/
2877
2878 void lp_set_name_resolve_order(char *new_order)
2879
2880   Globals.szNameResolveOrder = new_order;
2881 }
2882
2883 /***********************************************************
2884  Set the flag that says if kernel oplocks are available 
2885  (called by smbd).
2886 ************************************************************/
2887
2888 static BOOL kernel_oplocks_available = False;
2889
2890 void lp_set_kernel_oplocks(BOOL val)
2891 {
2892   /*
2893    * Only set this to True if kerenl
2894    * oplocks are really available and were
2895    * turned on in the smb.conf file.
2896    */
2897
2898   if(Globals.bKernelOplocks && val)
2899     kernel_oplocks_available = True;
2900   else
2901     kernel_oplocks_available = False;
2902 }
2903
2904 /***********************************************************
2905  Return True if kernel oplocks are available and were turned
2906  on in smb.conf.
2907 ************************************************************/
2908
2909 BOOL lp_kernel_oplocks(void)
2910 {
2911   return kernel_oplocks_available;
2912 }
2913
2914 /***********************************************************
2915  returns role of Samba server
2916 ************************************************************/
2917
2918 int lp_server_role(void)
2919 {
2920   return server_role;
2921 }
2922
2923 /***********************************************************
2924  If we are PDC then prefer us as DMB
2925 ************************************************************/
2926
2927 BOOL lp_domain_master(void)
2928 {
2929         if (Globals.bDomainMaster == Auto)
2930                 return (server_role == ROLE_DOMAIN_PDC);
2931
2932         return Globals.bDomainMaster;
2933 }
2934
2935 /***********************************************************
2936  If we are DMB then prefer us as LMB
2937 ************************************************************/
2938
2939 BOOL lp_preferred_master(void)
2940 {
2941         if (Globals.bPreferredMaster == Auto)
2942                 return (lp_local_master() && lp_domain_master());
2943
2944         return Globals.bPreferredMaster;
2945 }