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