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