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