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