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