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