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