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