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