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