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