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