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