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