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