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