source: trunk/samba/source/param/loadparm.c @ 30

Last change on this file since 30 was 30, checked in by Paul Smedley, 14 years ago

Code updated to Samba 3.0.25rc2 level

File size: 194.6 KB
Line 
1/*
2   Unix SMB/CIFS implementation.
3   Parameter loading functions
4   Copyright (C) Karl Auer 1993-1998
5
6   Largely re-written by Andrew Tridgell, September 1994
7
8   Copyright (C) Simo Sorce 2001
9   Copyright (C) Alexander Bokovoy 2002
10   Copyright (C) Stefan (metze) Metzmacher 2002
11   Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2003
12   
13   This program is free software; you can redistribute it and/or modify
14   it under the terms of the GNU General Public License as published by
15   the Free Software Foundation; either version 2 of the License, or
16   (at your option) any later version.
17   
18   This program is distributed in the hope that it will be useful,
19   but WITHOUT ANY WARRANTY; without even the implied warranty of
20   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21   GNU General Public License for more details.
22   
23   You should have received a copy of the GNU General Public License
24   along with this program; if not, write to the Free Software
25   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26*/
27
28/*
29 *  Load parameters.
30 *
31 *  This module provides suitable callback functions for the params
32 *  module. It builds the internal table of service details which is
33 *  then used by the rest of the server.
34 *
35 * To add a parameter:
36 *
37 * 1) add it to the global or service structure definition
38 * 2) add it to the parm_table
39 * 3) add it to the list of available functions (eg: using FN_GLOBAL_STRING())
40 * 4) If it's a global then initialise it in init_globals. If a local
41 *    (ie. service) parameter then initialise it in the sDefault structure
42 * 
43 *
44 * Notes:
45 *   The configuration file is processed sequentially for speed. It is NOT
46 *   accessed randomly as happens in 'real' Windows. For this reason, there
47 *   is a fair bit of sequence-dependent code here - ie., code which assumes
48 *   that certain things happen before others. In particular, the code which
49 *   happens at the boundary between sections is delicately poised, so be
50 *   careful!
51 *
52 */
53
54#include "includes.h"
55
56BOOL in_client = False;         /* Not in the client by default */
57BOOL bLoaded = False;
58
59extern pstring user_socket_options;
60extern enum protocol_types Protocol;
61extern userdom_struct current_user_info;
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 LP_SNUM_OK(i) (((i) >= 0) && ((i) < iNumServices) && (ServicePtrs != NULL) && ServicePtrs[(i)]->valid)
77#define VALID(i) (ServicePtrs != NULL && ServicePtrs[i]->valid)
78
79#define USERSHARE_VALID 1
80#define USERSHARE_PENDING_DELETE 2
81
82int keepalive = DEFAULT_KEEPALIVE;
83BOOL use_getwd_cache = True;
84
85extern int extra_time_offset;
86
87static BOOL defaults_saved = False;
88
89typedef struct _param_opt_struct param_opt_struct;
90struct _param_opt_struct {
91        param_opt_struct *prev, *next;
92        char *key;
93        char *value;
94        char **list;
95};
96
97/*
98 * This structure describes global (ie., server-wide) parameters.
99 */
100typedef struct {
101        char *smb_ports;
102        char *dos_charset;
103        char *unix_charset;
104        char *display_charset;
105        char *szPrintcapname;
106        char *szAddPortCommand;
107        char *szEnumPortsCommand;
108        char *szAddPrinterCommand;
109        char *szDeletePrinterCommand;
110        char *szOs2DriverMap;
111        char *szLockDir;
112        char *szPidDir;
113        char *szRootdir;
114        char *szDefaultService;
115        char *szGetQuota;
116        char *szSetQuota;
117        char *szMsgCommand;
118        char *szServerString;
119        char *szAutoServices;
120        char *szPasswdProgram;
121        char *szPasswdChat;
122        char *szLogFile;
123        char *szConfigFile;
124        char *szSMBPasswdFile;
125        char *szPrivateDir;
126        char *szPassdbBackend;
127        char **szPreloadModules;
128        char *szPasswordServer;
129        char *szSocketOptions;
130        char *szRealm;
131        char *szAfsUsernameMap;
132        int iAfsTokenLifetime;
133        char *szLogNtTokenCommand;
134        char *szUsernameMap;
135        char *szLogonScript;
136        char *szLogonPath;
137        char *szLogonDrive;
138        char *szLogonHome;
139        char **szWINSservers;
140        char **szInterfaces;
141        char *szRemoteAnnounce;
142        char *szRemoteBrowseSync;
143        char *szSocketAddress;
144        char *szNISHomeMapName;
145        char *szAnnounceVersion;        /* This is initialised in init_globals */
146        char *szWorkgroup;
147        char *szNetbiosName;
148        char **szNetbiosAliases;
149        char *szNetbiosScope;
150        char *szNameResolveOrder;
151        char *szPanicAction;
152        char *szAddUserScript;
153        char *szRenameUserScript;
154        char *szDelUserScript;
155        char *szAddGroupScript;
156        char *szDelGroupScript;
157        char *szAddUserToGroupScript;
158        char *szDelUserFromGroupScript;
159        char *szSetPrimaryGroupScript;
160        char *szAddMachineScript;
161        char *szShutdownScript;
162        char *szAbortShutdownScript;
163        char *szUsernameMapScript;
164        char *szCheckPasswordScript;
165        char *szWINSHook;
166        char *szUtmpDir;
167        char *szWtmpDir;
168        BOOL bUtmp;
169        char *szIdmapUID;
170        char *szIdmapGID;
171        BOOL bPassdbExpandExplicit;
172        int AlgorithmicRidBase;
173        char *szTemplateHomedir;
174        char *szTemplateShell;
175        char *szWinbindSeparator;
176        BOOL bWinbindEnumUsers;
177        BOOL bWinbindEnumGroups;
178        BOOL bWinbindUseDefaultDomain;
179        BOOL bWinbindTrustedDomainsOnly;
180        BOOL bWinbindNestedGroups;
181        BOOL bWinbindRefreshTickets;
182        BOOL bWinbindOfflineLogon;
183        BOOL bWinbindNormalizeNames;
184        char **szIdmapDomains;
185        char **szIdmapBackend; /* deprecated */
186        char *szIdmapAllocBackend;
187        char *szAddShareCommand;
188        char *szChangeShareCommand;
189        char *szDeleteShareCommand;
190        char **szEventLogs;
191        char *szGuestaccount;
192        char *szManglingMethod;
193        char **szServicesList;
194        char *szUsersharePath;
195        char *szUsershareTemplateShare;
196        char **szUsersharePrefixAllowList;
197        char **szUsersharePrefixDenyList;
198        int mangle_prefix;
199        int max_log_size;
200        char *szLogLevel;
201        int max_xmit;
202        int max_mux;
203        int max_open_files;
204        int open_files_db_hash_size;
205        int pwordlevel;
206        int unamelevel;
207        int deadtime;
208        int maxprotocol;
209        int minprotocol;
210        int security;
211        char **AuthMethods;
212        BOOL paranoid_server_security;
213        int maxdisksize;
214        int lpqcachetime;
215        int iMaxSmbdProcesses;
216        BOOL bDisableSpoolss;
217        int syslog;
218        int os_level;
219        int enhanced_browsing;
220        int max_ttl;
221        int max_wins_ttl;
222        int min_wins_ttl;
223        int lm_announce;
224        int lm_interval;
225        int announce_as;        /* This is initialised in init_globals */
226        int machine_password_timeout;
227        int map_to_guest;
228        int oplock_break_wait_time;
229        int winbind_cache_time;
230        int winbind_max_idle_children;
231        char **szWinbindNssInfo;
232        int iLockSpinTime;
233        char *szLdapMachineSuffix;
234        char *szLdapUserSuffix;
235        char *szLdapIdmapSuffix;
236        char *szLdapGroupSuffix;
237        int ldap_ssl;
238        char *szLdapSuffix;
239        char *szLdapAdminDn;
240        int iAclCompat;
241        char *szCupsServer;
242        char *szIPrintServer;
243        int ldap_passwd_sync; 
244        int ldap_replication_sleep;
245        int ldap_timeout; /* This is initialised in init_globals */
246        int ldap_page_size;
247        BOOL ldap_delete_dn;
248        BOOL bMsAddPrinterWizard;
249        BOOL bDNSproxy;
250        BOOL bWINSsupport;
251        BOOL bWINSproxy;
252        BOOL bLocalMaster;
253        BOOL bPreferredMaster;
254        BOOL bDomainMaster;
255        BOOL bDomainLogons;
256        BOOL bEncryptPasswords;
257        BOOL bUpdateEncrypt;
258        int  clientSchannel;
259        int  serverSchannel;
260        BOOL bNullPasswords;
261        BOOL bObeyPamRestrictions;
262        BOOL bLoadPrinters;
263        int PrintcapCacheTime;
264        BOOL bLargeReadwrite;
265        BOOL bReadRaw;
266        BOOL bWriteRaw;
267        BOOL bReadbmpx;
268        BOOL bSyslogOnly;
269        BOOL bBrowseList;
270        BOOL bNISHomeMap;
271        BOOL bTimeServer;
272        BOOL bBindInterfacesOnly;
273        BOOL bPamPasswordChange;
274        BOOL bUnixPasswdSync;
275        BOOL bPasswdChatDebug;
276        int iPasswdChatTimeout;
277        BOOL bTimestampLogs;
278        BOOL bNTSmbSupport;
279        BOOL bNTPipeSupport;
280        BOOL bNTStatusSupport;
281        BOOL bStatCache;
282        int iMaxStatCacheSize;
283        BOOL bKernelOplocks;
284        BOOL bAllowTrustedDomains;
285        BOOL bLanmanAuth;
286        BOOL bNTLMAuth;
287        BOOL bUseSpnego;
288        BOOL bClientLanManAuth;
289        BOOL bClientNTLMv2Auth;
290        BOOL bClientPlaintextAuth;
291        BOOL bClientUseSpnego;
292        BOOL bDebugPrefixTimestamp;
293        BOOL bDebugHiresTimestamp;
294        BOOL bDebugPid;
295        BOOL bDebugUid;
296        BOOL bEnableCoreFiles;
297        BOOL bHostMSDfs;
298        BOOL bUseMmap;
299        BOOL bHostnameLookups;
300        BOOL bUnixExtensions;
301        BOOL bDisableNetbios;
302        BOOL bUseKerberosKeytab;
303        BOOL bDeferSharingViolations;
304        BOOL bEnablePrivileges;
305        BOOL bASUSupport;
306        BOOL bUsershareOwnerOnly;
307        BOOL bUsershareAllowGuests;
308        int restrict_anonymous;
309        int name_cache_timeout;
310        int client_signing;
311        int server_signing;
312        int iUsershareMaxShares;
313        int iIdmapCacheTime;
314        int iIdmapNegativeCacheTime;
315
316        BOOL bResetOnZeroVC;
317        param_opt_struct *param_opt;
318} global;
319
320static global Globals;
321
322/*
323 * This structure describes a single service.
324 */
325typedef struct {
326        BOOL valid;
327        BOOL autoloaded;
328        int usershare;
329        time_t usershare_last_mod;
330        char *szService;
331        char *szPath;
332        char *szUsername;
333        char **szInvalidUsers;
334        char **szValidUsers;
335        char **szAdminUsers;
336        char *szCopy;
337        char *szInclude;
338        char *szPreExec;
339        char *szPostExec;
340        char *szRootPreExec;
341        char *szRootPostExec;
342        char *szCupsOptions;
343        char *szPrintcommand;
344        char *szLpqcommand;
345        char *szLprmcommand;
346        char *szLppausecommand;
347        char *szLpresumecommand;
348        char *szQueuepausecommand;
349        char *szQueueresumecommand;
350        char *szPrintername;
351        char *szPrintjobUsername;
352        char *szDontdescend;
353        char **szHostsallow;
354        char **szHostsdeny;
355        char *szMagicScript;
356        char *szMagicOutput;
357        char *szMangledMap;
358        char *szVetoFiles;
359        char *szHideFiles;
360        char *szVetoOplockFiles;
361        char *comment;
362        char *force_user;
363        char *force_group;
364        char **readlist;
365        char **writelist;
366        char **printer_admin;
367        char *volume;
368        char *fstype;
369        char **szVfsObjects;
370        char *szMSDfsProxy;
371        char *szAioWriteBehind;
372        char *szDfree;
373        int iMinPrintSpace;
374        int iMaxPrintJobs;
375        int iMaxReportedPrintJobs;
376        int iWriteCacheSize;
377        int iCreate_mask;
378        int iCreate_force_mode;
379        int iSecurity_mask;
380        int iSecurity_force_mode;
381        int iDir_mask;
382        int iDir_force_mode;
383        int iDir_Security_mask;
384        int iDir_Security_force_mode;
385        int iMaxConnections;
386        int iDefaultCase;
387        int iPrinting;
388        int iOplockContentionLimit;
389        int iCSCPolicy;
390        int iBlock_size;
391        int iDfreeCacheTime;
392        BOOL bPreexecClose;
393        BOOL bRootpreexecClose;
394        int  iCaseSensitive;
395        BOOL bCasePreserve;
396        BOOL bShortCasePreserve;
397        BOOL bHideDotFiles;
398        BOOL bHideSpecialFiles;
399        BOOL bHideUnReadable;
400        BOOL bHideUnWriteableFiles;
401        BOOL bBrowseable;
402        BOOL bAvailable;
403        BOOL bRead_only;
404        BOOL bNo_set_dir;
405        BOOL bGuest_only;
406        BOOL bGuest_ok;
407        BOOL bPrint_ok;
408        BOOL bMap_system;
409        BOOL bMap_hidden;
410        BOOL bMap_archive;
411        BOOL bStoreDosAttributes;
412        BOOL bDmapiSupport;
413        BOOL bLocking;
414        int iStrictLocking;
415        BOOL bPosixLocking;
416        BOOL bShareModes;
417        BOOL bOpLocks;
418        BOOL bLevel2OpLocks;
419        BOOL bOnlyUser;
420        BOOL bMangledNames;
421        BOOL bWidelinks;
422        BOOL bSymlinks;
423        BOOL bSyncAlways;
424        BOOL bStrictAllocate;
425        BOOL bStrictSync;
426        char magic_char;
427        BOOL *copymap;
428        BOOL bDeleteReadonly;
429        BOOL bFakeOplocks;
430        BOOL bDeleteVetoFiles;
431        BOOL bDosFilemode;
432        BOOL bDosFiletimes;
433        BOOL bDosFiletimeResolution;
434        BOOL bFakeDirCreateTimes;
435        BOOL bBlockingLocks;
436        BOOL bInheritPerms;
437        BOOL bInheritACLS;
438        BOOL bInheritOwner;
439        BOOL bMSDfsRoot;
440        BOOL bUseClientDriver;
441        BOOL bDefaultDevmode;
442        BOOL bForcePrintername;
443        BOOL bNTAclSupport;
444        BOOL bForceUnknownAclUser;
445        BOOL bUseSendfile;
446        BOOL bProfileAcls;
447        BOOL bMap_acl_inherit;
448        BOOL bAfs_Share;
449        BOOL bEASupport;
450        BOOL bAclCheckPermissions;
451        BOOL bAclMapFullControl;
452        BOOL bAclGroupControl;
453        BOOL bChangeNotify;
454        BOOL bKernelChangeNotify;
455        int iallocation_roundup_size;
456        int iAioReadSize;
457        int iAioWriteSize;
458        int iMap_readonly;
459        param_opt_struct *param_opt;
460
461        char dummy[3];          /* for alignment */
462} service;
463
464
465/* This is a default service used to prime a services structure */
466static service sDefault = {
467        True,                   /* valid */
468        False,                  /* not autoloaded */
469        0,                      /* not a usershare */
470        (time_t)0,              /* No last mod time */
471        NULL,                   /* szService */
472        NULL,                   /* szPath */
473        NULL,                   /* szUsername */
474        NULL,                   /* szInvalidUsers */
475        NULL,                   /* szValidUsers */
476        NULL,                   /* szAdminUsers */
477        NULL,                   /* szCopy */
478        NULL,                   /* szInclude */
479        NULL,                   /* szPreExec */
480        NULL,                   /* szPostExec */
481        NULL,                   /* szRootPreExec */
482        NULL,                   /* szRootPostExec */
483        NULL,                   /* szCupsOptions */
484        NULL,                   /* szPrintcommand */
485        NULL,                   /* szLpqcommand */
486        NULL,                   /* szLprmcommand */
487        NULL,                   /* szLppausecommand */
488        NULL,                   /* szLpresumecommand */
489        NULL,                   /* szQueuepausecommand */
490        NULL,                   /* szQueueresumecommand */
491        NULL,                   /* szPrintername */
492        NULL,                   /* szPrintjobUsername */
493        NULL,                   /* szDontdescend */
494        NULL,                   /* szHostsallow */
495        NULL,                   /* szHostsdeny */
496        NULL,                   /* szMagicScript */
497        NULL,                   /* szMagicOutput */
498        NULL,                   /* szMangledMap */
499        NULL,                   /* szVetoFiles */
500        NULL,                   /* szHideFiles */
501        NULL,                   /* szVetoOplockFiles */
502        NULL,                   /* comment */
503        NULL,                   /* force user */
504        NULL,                   /* force group */
505        NULL,                   /* readlist */
506        NULL,                   /* writelist */
507        NULL,                   /* printer admin */
508        NULL,                   /* volume */
509        NULL,                   /* fstype */
510        NULL,                   /* vfs objects */
511        NULL,                   /* szMSDfsProxy */
512        NULL,                   /* szAioWriteBehind */
513        NULL,                   /* szDfree */
514        0,                      /* iMinPrintSpace */
515        1000,                   /* iMaxPrintJobs */
516        0,                      /* iMaxReportedPrintJobs */
517        0,                      /* iWriteCacheSize */
518        0744,                   /* iCreate_mask */
519        0000,                   /* iCreate_force_mode */
520        0777,                   /* iSecurity_mask */
521        0,                      /* iSecurity_force_mode */
522        0755,                   /* iDir_mask */
523        0000,                   /* iDir_force_mode */
524        0777,                   /* iDir_Security_mask */
525        0,                      /* iDir_Security_force_mode */
526        0,                      /* iMaxConnections */
527        CASE_LOWER,             /* iDefaultCase */
528        DEFAULT_PRINTING,       /* iPrinting */
529        2,                      /* iOplockContentionLimit */
530        0,                      /* iCSCPolicy */
531        1024,                   /* iBlock_size */
532        0,                      /* iDfreeCacheTime */
533        False,                  /* bPreexecClose */
534        False,                  /* bRootpreexecClose */
535        Auto,                   /* case sensitive */
536        True,                   /* case preserve */
537        True,                   /* short case preserve */
538        True,                   /* bHideDotFiles */
539        False,                  /* bHideSpecialFiles */
540        False,                  /* bHideUnReadable */
541        False,                  /* bHideUnWriteableFiles */
542        True,                   /* bBrowseable */
543        True,                   /* bAvailable */
544        True,                   /* bRead_only */
545        True,                   /* bNo_set_dir */
546        False,                  /* bGuest_only */
547        False,                  /* bGuest_ok */
548        False,                  /* bPrint_ok */
549        False,                  /* bMap_system */
550        False,                  /* bMap_hidden */
551        True,                   /* bMap_archive */
552        False,                  /* bStoreDosAttributes */
553        False,                  /* bDmapiSupport */
554        True,                   /* bLocking */
555        Auto,                   /* iStrictLocking */
556        True,                   /* bPosixLocking */
557        True,                   /* bShareModes */
558        True,                   /* bOpLocks */
559        True,                   /* bLevel2OpLocks */
560        False,                  /* bOnlyUser */
561        True,                   /* bMangledNames */
562        True,                   /* bWidelinks */
563        True,                   /* bSymlinks */
564        False,                  /* bSyncAlways */
565        False,                  /* bStrictAllocate */
566        False,                  /* bStrictSync */
567        '~',                    /* magic char */
568        NULL,                   /* copymap */
569        False,                  /* bDeleteReadonly */
570        False,                  /* bFakeOplocks */
571        False,                  /* bDeleteVetoFiles */
572        False,                  /* bDosFilemode */
573        True,                   /* bDosFiletimes */
574        False,                  /* bDosFiletimeResolution */
575        False,                  /* bFakeDirCreateTimes */
576        True,                   /* bBlockingLocks */
577        False,                  /* bInheritPerms */
578        False,                  /* bInheritACLS */
579        False,                  /* bInheritOwner */
580        False,                  /* bMSDfsRoot */
581        False,                  /* bUseClientDriver */
582        True,                   /* bDefaultDevmode */
583        False,                  /* bForcePrintername */
584        True,                   /* bNTAclSupport */
585        False,                  /* bForceUnknownAclUser */
586        False,                  /* bUseSendfile */
587        False,                  /* bProfileAcls */
588        False,                  /* bMap_acl_inherit */
589        False,                  /* bAfs_Share */
590        False,                  /* bEASupport */
591        True,                   /* bAclCheckPermissions */
592        True,                   /* bAclMapFullControl */
593        False,                  /* bAclGroupControl */
594        True,                   /* bChangeNotify */
595        True,                   /* bKernelChangeNotify */
596        SMB_ROUNDUP_ALLOCATION_SIZE,            /* iallocation_roundup_size */
597        0,                      /* iAioReadSize */
598        0,                      /* iAioWriteSize */
599        MAP_READONLY_YES,       /* iMap_readonly */
600       
601        NULL,                   /* Parametric options */
602
603        ""                      /* dummy */
604};
605
606/* local variables */
607static service **ServicePtrs = NULL;
608static int iNumServices = 0;
609static int iServiceIndex = 0;
610static TDB_CONTEXT *ServiceHash;
611static int *invalid_services = NULL;
612static int num_invalid_services = 0;
613static BOOL bInGlobalSection = True;
614static BOOL bGlobalOnly = False;
615static int server_role;
616static int default_server_announce;
617
618#define NUMPARAMETERS (sizeof(parm_table) / sizeof(struct parm_struct))
619
620/* prototypes for the special type handlers */
621static BOOL handle_include( int snum, const char *pszParmValue, char **ptr);
622static BOOL handle_copy( int snum, const char *pszParmValue, char **ptr);
623static BOOL handle_netbios_name( int snum, const char *pszParmValue, char **ptr);
624static BOOL handle_idmap_uid( int snum, const char *pszParmValue, char **ptr);
625static BOOL handle_idmap_gid( int snum, const char *pszParmValue, char **ptr);
626static BOOL handle_debug_list( int snum, const char *pszParmValue, char **ptr );
627static BOOL handle_workgroup( int snum, const char *pszParmValue, char **ptr );
628static BOOL handle_netbios_aliases( int snum, const char *pszParmValue, char **ptr );
629static BOOL handle_netbios_scope( int snum, const char *pszParmValue, char **ptr );
630static BOOL handle_charset( int snum, const char *pszParmValue, char **ptr );
631static BOOL handle_printing( int snum, const char *pszParmValue, char **ptr);
632
633static void set_server_role(void);
634static void set_default_server_announce_type(void);
635static void set_allowed_client_auth(void);
636
637static const struct enum_list enum_protocol[] = {
638        {PROTOCOL_NT1, "NT1"},
639        {PROTOCOL_LANMAN2, "LANMAN2"},
640        {PROTOCOL_LANMAN1, "LANMAN1"},
641        {PROTOCOL_CORE, "CORE"},
642        {PROTOCOL_COREPLUS, "COREPLUS"},
643        {PROTOCOL_COREPLUS, "CORE+"},
644        {-1, NULL}
645};
646
647static const struct enum_list enum_security[] = {
648        {SEC_SHARE, "SHARE"},
649        {SEC_USER, "USER"},
650        {SEC_SERVER, "SERVER"},
651        {SEC_DOMAIN, "DOMAIN"},
652#ifdef HAVE_ADS
653        {SEC_ADS, "ADS"},
654#endif
655        {-1, NULL}
656};
657
658static const struct enum_list enum_printing[] = {
659        {PRINT_SYSV, "sysv"},
660        {PRINT_AIX, "aix"},
661        {PRINT_HPUX, "hpux"},
662        {PRINT_BSD, "bsd"},
663        {PRINT_QNX, "qnx"},
664        {PRINT_PLP, "plp"},
665        {PRINT_LPRNG, "lprng"},
666        {PRINT_CUPS, "cups"},
667        {PRINT_IPRINT, "iprint"},
668        {PRINT_LPRNT, "nt"},
669        {PRINT_LPROS2, "os2"},
670#ifdef DEVELOPER
671        {PRINT_TEST, "test"},
672        {PRINT_VLP, "vlp"},
673#endif /* DEVELOPER */
674        {-1, NULL}
675};
676
677static const struct enum_list enum_ldap_ssl[] = {
678        {LDAP_SSL_OFF, "no"},
679        {LDAP_SSL_OFF, "No"},
680        {LDAP_SSL_OFF, "off"},
681        {LDAP_SSL_OFF, "Off"},
682        {LDAP_SSL_START_TLS, "start tls"},
683        {LDAP_SSL_START_TLS, "Start_tls"},
684        {-1, NULL}
685};
686
687static const struct enum_list enum_ldap_passwd_sync[] = {
688        {LDAP_PASSWD_SYNC_OFF, "no"},
689        {LDAP_PASSWD_SYNC_OFF, "No"},
690        {LDAP_PASSWD_SYNC_OFF, "off"},
691        {LDAP_PASSWD_SYNC_OFF, "Off"},
692        {LDAP_PASSWD_SYNC_ON, "Yes"},
693        {LDAP_PASSWD_SYNC_ON, "yes"},
694        {LDAP_PASSWD_SYNC_ON, "on"},
695        {LDAP_PASSWD_SYNC_ON, "On"},
696        {LDAP_PASSWD_SYNC_ONLY, "Only"},
697        {LDAP_PASSWD_SYNC_ONLY, "only"},
698        {-1, NULL}
699};
700
701/* Types of machine we can announce as. */
702#define ANNOUNCE_AS_NT_SERVER 1
703#define ANNOUNCE_AS_WIN95 2
704#define ANNOUNCE_AS_WFW 3
705#define ANNOUNCE_AS_NT_WORKSTATION 4
706
707static const struct enum_list enum_announce_as[] = {
708        {ANNOUNCE_AS_NT_SERVER, "NT"},
709        {ANNOUNCE_AS_NT_SERVER, "NT Server"},
710        {ANNOUNCE_AS_NT_WORKSTATION, "NT Workstation"},
711        {ANNOUNCE_AS_WIN95, "win95"},
712        {ANNOUNCE_AS_WFW, "WfW"},
713        {-1, NULL}
714};
715
716static const struct enum_list enum_map_readonly[] = {
717        {MAP_READONLY_NO, "no"},
718        {MAP_READONLY_NO, "false"},
719        {MAP_READONLY_NO, "0"},
720        {MAP_READONLY_YES, "yes"},
721        {MAP_READONLY_YES, "true"},
722        {MAP_READONLY_YES, "1"},
723        {MAP_READONLY_PERMISSIONS, "permissions"},
724        {MAP_READONLY_PERMISSIONS, "perms"},
725        {-1, NULL}
726};
727
728static const struct enum_list enum_case[] = {
729        {CASE_LOWER, "lower"},
730        {CASE_UPPER, "upper"},
731        {-1, NULL}
732};
733
734static const struct enum_list enum_bool_auto[] = {
735        {False, "No"},
736        {False, "False"},
737        {False, "0"},
738        {True, "Yes"},
739        {True, "True"},
740        {True, "1"},
741        {Auto, "Auto"},
742        {-1, NULL}
743};
744
745/* Client-side offline caching policy types */
746#define CSC_POLICY_MANUAL 0
747#define CSC_POLICY_DOCUMENTS 1
748#define CSC_POLICY_PROGRAMS 2
749#define CSC_POLICY_DISABLE 3
750
751static const struct enum_list enum_csc_policy[] = {
752        {CSC_POLICY_MANUAL, "manual"},
753        {CSC_POLICY_DOCUMENTS, "documents"},
754        {CSC_POLICY_PROGRAMS, "programs"},
755        {CSC_POLICY_DISABLE, "disable"},
756        {-1, NULL}
757};
758
759/* SMB signing types. */
760static const struct enum_list enum_smb_signing_vals[] = {
761        {False, "No"},
762        {False, "False"},
763        {False, "0"},
764        {False, "Off"},
765        {False, "disabled"},
766        {True, "Yes"},
767        {True, "True"},
768        {True, "1"},
769        {True, "On"},
770        {True, "enabled"},
771        {Auto, "auto"},
772        {Required, "required"},
773        {Required, "mandatory"},
774        {Required, "force"},
775        {Required, "forced"},
776        {Required, "enforced"},
777        {-1, NULL}
778};
779
780/* ACL compatibility options. */
781static const struct enum_list enum_acl_compat_vals[] = {
782    { ACL_COMPAT_AUTO, "auto" },
783    { ACL_COMPAT_WINNT, "winnt" },
784    { ACL_COMPAT_WIN2K, "win2k" },
785    { -1, NULL}
786};
787
788/*
789   Do you want session setups at user level security with a invalid
790   password to be rejected or allowed in as guest? WinNT rejects them
791   but it can be a pain as it means "net view" needs to use a password
792
793   You have 3 choices in the setting of map_to_guest:
794
795   "Never" means session setups with an invalid password
796   are rejected. This is the default.
797
798   "Bad User" means session setups with an invalid password
799   are rejected, unless the username does not exist, in which case it
800   is treated as a guest login
801
802   "Bad Password" means session setups with an invalid password
803   are treated as a guest login
804
805   Note that map_to_guest only has an effect in user or server
806   level security.
807*/
808
809static const struct enum_list enum_map_to_guest[] = {
810        {NEVER_MAP_TO_GUEST, "Never"},
811        {MAP_TO_GUEST_ON_BAD_USER, "Bad User"},
812        {MAP_TO_GUEST_ON_BAD_PASSWORD, "Bad Password"},
813        {MAP_TO_GUEST_ON_BAD_UID, "Bad Uid"},
814        {-1, NULL}
815};
816
817/* Note: We do not initialise the defaults union - it is not allowed in ANSI C
818 *
819 * The FLAG_HIDE is explicit. Paramters set this way do NOT appear in any edit
820 * screen in SWAT. This is used to exclude parameters as well as to squash all
821 * parameters that have been duplicated by pseudonyms.
822 *
823 * NOTE: To display a parameter in BASIC view set FLAG_BASIC
824 *       Any parameter that does NOT have FLAG_ADVANCED will not disply at all
825 *       Set FLAG_SHARE and FLAG_PRINT to specifically display parameters in
826 *        respective views.
827 *
828 * NOTE2: Handling of duplicated (synonym) paramters:
829 *      Only the first occurance of a parameter should be enabled by FLAG_BASIC
830 *      and/or FLAG_ADVANCED. All duplicates following the first mention should be
831 *      set to FLAG_HIDE. ie: Make you must place the parameter that has the preferred
832 *      name first, and all synonyms must follow it with the FLAG_HIDE attribute.
833 */
834
835static struct parm_struct parm_table[] = {
836        {N_("Base Options"), P_SEP, P_SEPARATOR}, 
837
838        {"dos charset", P_STRING, P_GLOBAL, &Globals.dos_charset, handle_charset, NULL, FLAG_ADVANCED}, 
839        {"unix charset", P_STRING, P_GLOBAL, &Globals.unix_charset, handle_charset, NULL, FLAG_ADVANCED}, 
840        {"display charset", P_STRING, P_GLOBAL, &Globals.display_charset, handle_charset, NULL, FLAG_ADVANCED}, 
841        {"comment", P_STRING, P_LOCAL, &sDefault.comment, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT}, 
842        {"path", P_STRING, P_LOCAL, &sDefault.szPath, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT}, 
843        {"directory", P_STRING, P_LOCAL, &sDefault.szPath, NULL, NULL, FLAG_HIDE}, 
844        {"workgroup", P_USTRING, P_GLOBAL, &Globals.szWorkgroup, handle_workgroup, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD}, 
845#ifdef WITH_ADS
846        {"realm", P_USTRING, P_GLOBAL, &Globals.szRealm, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD}, 
847#endif
848        {"netbios name", P_USTRING, P_GLOBAL, &Globals.szNetbiosName, handle_netbios_name, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD}, 
849        {"netbios aliases", P_LIST, P_GLOBAL, &Globals.szNetbiosAliases, handle_netbios_aliases,  NULL, FLAG_ADVANCED}, 
850        {"netbios scope", P_USTRING, P_GLOBAL, &Globals.szNetbiosScope, handle_netbios_scope,  NULL, FLAG_ADVANCED}, 
851        {"server string", P_STRING, P_GLOBAL, &Globals.szServerString, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED }, 
852        {"interfaces", P_LIST, P_GLOBAL, &Globals.szInterfaces, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD}, 
853        {"bind interfaces only", P_BOOL, P_GLOBAL, &Globals.bBindInterfacesOnly, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD}, 
854
855        {N_("Security Options"), P_SEP, P_SEPARATOR}, 
856
857        {"security", P_ENUM, P_GLOBAL, &Globals.security, NULL, enum_security, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD}, 
858        {"auth methods", P_LIST, P_GLOBAL, &Globals.AuthMethods, NULL, NULL, FLAG_ADVANCED}, 
859        {"encrypt passwords", P_BOOL, P_GLOBAL, &Globals.bEncryptPasswords, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD}, 
860        {"update encrypted", P_BOOL, P_GLOBAL, &Globals.bUpdateEncrypt, NULL, NULL, FLAG_ADVANCED}, 
861        {"client schannel", P_ENUM, P_GLOBAL, &Globals.clientSchannel, NULL, enum_bool_auto, FLAG_BASIC | FLAG_ADVANCED}, 
862        {"server schannel", P_ENUM, P_GLOBAL, &Globals.serverSchannel, NULL, enum_bool_auto, FLAG_BASIC | FLAG_ADVANCED}, 
863        {"allow trusted domains", P_BOOL, P_GLOBAL, &Globals.bAllowTrustedDomains, NULL, NULL, FLAG_ADVANCED}, 
864        {"map to guest", P_ENUM, P_GLOBAL, &Globals.map_to_guest, NULL, enum_map_to_guest, FLAG_ADVANCED}, 
865        {"null passwords", P_BOOL, P_GLOBAL, &Globals.bNullPasswords, NULL, NULL, FLAG_ADVANCED}, 
866        {"obey pam restrictions", P_BOOL, P_GLOBAL, &Globals.bObeyPamRestrictions, NULL, NULL, FLAG_ADVANCED}, 
867        {"password server", P_STRING, P_GLOBAL, &Globals.szPasswordServer, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD}, 
868        {"smb passwd file", P_STRING, P_GLOBAL, &Globals.szSMBPasswdFile, NULL, NULL, FLAG_ADVANCED}, 
869        {"private dir", P_STRING, P_GLOBAL, &Globals.szPrivateDir, NULL, NULL, FLAG_ADVANCED}, 
870        {"passdb backend", P_STRING, P_GLOBAL, &Globals.szPassdbBackend, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD}, 
871        {"algorithmic rid base", P_INTEGER, P_GLOBAL, &Globals.AlgorithmicRidBase, NULL, NULL, FLAG_ADVANCED}, 
872        {"root directory", P_STRING, P_GLOBAL, &Globals.szRootdir, NULL, NULL, FLAG_ADVANCED}, 
873        {"root dir", P_STRING, P_GLOBAL, &Globals.szRootdir, NULL, NULL, FLAG_HIDE}, 
874        {"root", P_STRING, P_GLOBAL, &Globals.szRootdir, NULL, NULL, FLAG_HIDE}, 
875        {"guest account", P_STRING, P_GLOBAL, &Globals.szGuestaccount, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED}, 
876        {"enable privileges", P_BOOL, P_GLOBAL, &Globals.bEnablePrivileges, NULL, NULL, FLAG_ADVANCED}, 
877
878        {"pam password change", P_BOOL, P_GLOBAL, &Globals.bPamPasswordChange, NULL, NULL, FLAG_ADVANCED}, 
879        {"passwd program", P_STRING, P_GLOBAL, &Globals.szPasswdProgram, NULL, NULL, FLAG_ADVANCED}, 
880        {"passwd chat", P_STRING, P_GLOBAL, &Globals.szPasswdChat, NULL, NULL, FLAG_ADVANCED}, 
881        {"passwd chat debug", P_BOOL, P_GLOBAL, &Globals.bPasswdChatDebug, NULL, NULL, FLAG_ADVANCED}, 
882        {"passwd chat timeout", P_INTEGER, P_GLOBAL, &Globals.iPasswdChatTimeout, NULL, NULL, FLAG_ADVANCED}, 
883        {"check password script", P_STRING, P_GLOBAL, &Globals.szCheckPasswordScript, NULL, NULL, FLAG_ADVANCED}, 
884        {"username map", P_STRING, P_GLOBAL, &Globals.szUsernameMap, NULL, NULL, FLAG_ADVANCED}, 
885        {"password level", P_INTEGER, P_GLOBAL, &Globals.pwordlevel, NULL, NULL, FLAG_ADVANCED}, 
886        {"username level", P_INTEGER, P_GLOBAL, &Globals.unamelevel, NULL, NULL, FLAG_ADVANCED}, 
887        {"unix password sync", P_BOOL, P_GLOBAL, &Globals.bUnixPasswdSync, NULL, NULL, FLAG_ADVANCED}, 
888        {"restrict anonymous", P_INTEGER, P_GLOBAL, &Globals.restrict_anonymous, NULL, NULL, FLAG_ADVANCED}, 
889        {"lanman auth", P_BOOL, P_GLOBAL, &Globals.bLanmanAuth, NULL, NULL, FLAG_ADVANCED}, 
890        {"ntlm auth", P_BOOL, P_GLOBAL, &Globals.bNTLMAuth, NULL, NULL, FLAG_ADVANCED}, 
891        {"client NTLMv2 auth", P_BOOL, P_GLOBAL, &Globals.bClientNTLMv2Auth, NULL, NULL, FLAG_ADVANCED}, 
892        {"client lanman auth", P_BOOL, P_GLOBAL, &Globals.bClientLanManAuth, NULL, NULL, FLAG_ADVANCED}, 
893        {"client plaintext auth", P_BOOL, P_GLOBAL, &Globals.bClientPlaintextAuth, NULL, NULL, FLAG_ADVANCED}, 
894
895        {"username", P_STRING, P_LOCAL, &sDefault.szUsername, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, 
896        {"user", P_STRING, P_LOCAL, &sDefault.szUsername, NULL, NULL, FLAG_HIDE}, 
897        {"users", P_STRING, P_LOCAL, &sDefault.szUsername, NULL, NULL, FLAG_HIDE}, 
898
899        {"invalid users", P_LIST, P_LOCAL, &sDefault.szInvalidUsers, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, 
900        {"valid users", P_LIST, P_LOCAL, &sDefault.szValidUsers, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, 
901        {"admin users", P_LIST, P_LOCAL, &sDefault.szAdminUsers, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, 
902        {"read list", P_LIST, P_LOCAL, &sDefault.readlist, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, 
903        {"write list", P_LIST, P_LOCAL, &sDefault.writelist, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, 
904        {"printer admin", P_LIST, P_LOCAL, &sDefault.printer_admin, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_PRINT | FLAG_DEPRECATED }, 
905        {"force user", P_STRING, P_LOCAL, &sDefault.force_user, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
906        {"force group", P_STRING, P_LOCAL, &sDefault.force_group, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
907        {"group", P_STRING, P_LOCAL, &sDefault.force_group, NULL, NULL, FLAG_ADVANCED}, 
908
909        {"read only", P_BOOL, P_LOCAL, &sDefault.bRead_only, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE}, 
910        {"write ok", P_BOOLREV, P_LOCAL, &sDefault.bRead_only, NULL, NULL, FLAG_HIDE}, 
911        {"writeable", P_BOOLREV, P_LOCAL, &sDefault.bRead_only, NULL, NULL, FLAG_HIDE}, 
912        {"writable", P_BOOLREV, P_LOCAL, &sDefault.bRead_only, NULL, NULL, FLAG_HIDE}, 
913
914        {"acl check permissions", P_BOOL, P_LOCAL, &sDefault.bAclCheckPermissions, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE},
915        {"acl group control", P_BOOL, P_LOCAL, &sDefault.bAclGroupControl, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE | FLAG_DEPRECATED },
916        {"acl map full control", P_BOOL, P_LOCAL, &sDefault.bAclMapFullControl, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE},
917        {"create mask", P_OCTAL, P_LOCAL, &sDefault.iCreate_mask, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, 
918        {"create mode", P_OCTAL, P_LOCAL, &sDefault.iCreate_mask, NULL, NULL, FLAG_HIDE}, 
919        {"force create mode", P_OCTAL, P_LOCAL, &sDefault.iCreate_force_mode, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, 
920        {"security mask", P_OCTAL, P_LOCAL, &sDefault.iSecurity_mask, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, 
921        {"force security mode", P_OCTAL, P_LOCAL, &sDefault.iSecurity_force_mode, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, 
922        {"directory mask", P_OCTAL, P_LOCAL, &sDefault.iDir_mask, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, 
923        {"directory mode", P_OCTAL, P_LOCAL, &sDefault.iDir_mask, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL}, 
924        {"force directory mode", P_OCTAL, P_LOCAL, &sDefault.iDir_force_mode, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, 
925        {"directory security mask", P_OCTAL, P_LOCAL, &sDefault.iDir_Security_mask, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, 
926        {"force directory security mode", P_OCTAL, P_LOCAL, &sDefault.iDir_Security_force_mode, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, 
927        {"force unknown acl user", P_BOOL, P_LOCAL, &sDefault.bForceUnknownAclUser, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE},
928        {"inherit permissions", P_BOOL, P_LOCAL, &sDefault.bInheritPerms, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
929        {"inherit acls", P_BOOL, P_LOCAL, &sDefault.bInheritACLS, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
930        {"inherit owner", P_BOOL, P_LOCAL, &sDefault.bInheritOwner, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
931        {"guest only", P_BOOL, P_LOCAL, &sDefault.bGuest_only, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
932        {"only guest", P_BOOL, P_LOCAL, &sDefault.bGuest_only, NULL, NULL, FLAG_HIDE}, 
933
934        {"guest ok", P_BOOL, P_LOCAL, &sDefault.bGuest_ok, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT}, 
935        {"public", P_BOOL, P_LOCAL, &sDefault.bGuest_ok, NULL, NULL, FLAG_HIDE}, 
936
937        {"only user", P_BOOL, P_LOCAL, &sDefault.bOnlyUser, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_DEPRECATED}, 
938        {"hosts allow", P_LIST, P_LOCAL, &sDefault.szHostsallow, NULL, NULL, FLAG_GLOBAL | FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT}, 
939        {"allow hosts", P_LIST, P_LOCAL, &sDefault.szHostsallow, NULL, NULL, FLAG_HIDE}, 
940        {"hosts deny", P_LIST, P_LOCAL, &sDefault.szHostsdeny, NULL, NULL, FLAG_GLOBAL | FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT}, 
941        {"deny hosts", P_LIST, P_LOCAL, &sDefault.szHostsdeny, NULL, NULL, FLAG_HIDE}, 
942        {"preload modules", P_LIST, P_GLOBAL, &Globals.szPreloadModules, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL}, 
943        {"use kerberos keytab", P_BOOL, P_GLOBAL, &Globals.bUseKerberosKeytab, NULL, NULL, FLAG_ADVANCED}, 
944
945        {N_("Logging Options"), P_SEP, P_SEPARATOR}, 
946
947        {"log level", P_STRING, P_GLOBAL, &Globals.szLogLevel, handle_debug_list, NULL, FLAG_ADVANCED}, 
948        {"debuglevel", P_STRING, P_GLOBAL, &Globals.szLogLevel, handle_debug_list, NULL, FLAG_HIDE}, 
949        {"syslog", P_INTEGER, P_GLOBAL, &Globals.syslog, NULL, NULL, FLAG_ADVANCED}, 
950        {"syslog only", P_BOOL, P_GLOBAL, &Globals.bSyslogOnly, NULL, NULL, FLAG_ADVANCED}, 
951        {"log file", P_STRING, P_GLOBAL, &Globals.szLogFile, NULL, NULL, FLAG_ADVANCED}, 
952
953        {"max log size", P_INTEGER, P_GLOBAL, &Globals.max_log_size, NULL, NULL, FLAG_ADVANCED}, 
954        {"debug timestamp", P_BOOL, P_GLOBAL, &Globals.bTimestampLogs, NULL, NULL, FLAG_ADVANCED}, 
955        {"timestamp logs", P_BOOL, P_GLOBAL, &Globals.bTimestampLogs, NULL, NULL, FLAG_ADVANCED}, 
956        {"debug prefix timestamp", P_BOOL, P_GLOBAL, &Globals.bDebugPrefixTimestamp, NULL, NULL, FLAG_ADVANCED}, 
957        {"debug hires timestamp", P_BOOL, P_GLOBAL, &Globals.bDebugHiresTimestamp, NULL, NULL, FLAG_ADVANCED}, 
958        {"debug pid", P_BOOL, P_GLOBAL, &Globals.bDebugPid, NULL, NULL, FLAG_ADVANCED}, 
959        {"debug uid", P_BOOL, P_GLOBAL, &Globals.bDebugUid, NULL, NULL, FLAG_ADVANCED}, 
960        {"enable core files", P_BOOL, P_GLOBAL, &Globals.bEnableCoreFiles, NULL, NULL, FLAG_ADVANCED},
961
962        {N_("Protocol Options"), P_SEP, P_SEPARATOR}, 
963
964        {"allocation roundup size", P_INTEGER, P_LOCAL, &sDefault.iallocation_roundup_size, NULL, NULL, FLAG_ADVANCED}, 
965        {"aio read size", P_INTEGER, P_LOCAL, &sDefault.iAioReadSize, NULL, NULL, FLAG_ADVANCED}, 
966        {"aio write size", P_INTEGER, P_LOCAL, &sDefault.iAioWriteSize, NULL, NULL, FLAG_ADVANCED}, 
967        {"aio write behind", P_STRING, P_LOCAL, &sDefault.szAioWriteBehind, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL }, 
968        {"smb ports", P_STRING, P_GLOBAL, &Globals.smb_ports, NULL, NULL, FLAG_ADVANCED}, 
969        {"large readwrite", P_BOOL, P_GLOBAL, &Globals.bLargeReadwrite, NULL, NULL, FLAG_ADVANCED}, 
970        {"max protocol", P_ENUM, P_GLOBAL, &Globals.maxprotocol, NULL, enum_protocol, FLAG_ADVANCED}, 
971        {"protocol", P_ENUM, P_GLOBAL, &Globals.maxprotocol, NULL, enum_protocol, FLAG_ADVANCED}, 
972        {"min protocol", P_ENUM, P_GLOBAL, &Globals.minprotocol, NULL, enum_protocol, FLAG_ADVANCED}, 
973        {"read bmpx", P_BOOL, P_GLOBAL, &Globals.bReadbmpx, NULL, NULL, FLAG_ADVANCED}, 
974        {"read raw", P_BOOL, P_GLOBAL, &Globals.bReadRaw, NULL, NULL, FLAG_ADVANCED}, 
975        {"write raw", P_BOOL, P_GLOBAL, &Globals.bWriteRaw, NULL, NULL, FLAG_ADVANCED}, 
976        {"disable netbios", P_BOOL, P_GLOBAL, &Globals.bDisableNetbios, NULL, NULL, FLAG_ADVANCED}, 
977        {"reset on zero vc", P_BOOL, P_GLOBAL, &Globals.bResetOnZeroVC, NULL, NULL, FLAG_ADVANCED}, 
978
979        {"acl compatibility", P_ENUM, P_GLOBAL, &Globals.iAclCompat, NULL,  enum_acl_compat_vals, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
980        {"defer sharing violations", P_BOOL, P_GLOBAL, &Globals.bDeferSharingViolations, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL},
981        {"ea support", P_BOOL, P_LOCAL, &sDefault.bEASupport, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
982        {"nt acl support", P_BOOL, P_LOCAL, &sDefault.bNTAclSupport, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
983        {"nt pipe support", P_BOOL, P_GLOBAL, &Globals.bNTPipeSupport, NULL, NULL, FLAG_ADVANCED}, 
984        {"nt status support", P_BOOL, P_GLOBAL, &Globals.bNTStatusSupport, NULL, NULL, FLAG_ADVANCED}, 
985        {"profile acls", P_BOOL, P_LOCAL, &sDefault.bProfileAcls, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, 
986
987        {"announce version", P_STRING, P_GLOBAL, &Globals.szAnnounceVersion, NULL, NULL, FLAG_ADVANCED}, 
988        {"announce as", P_ENUM, P_GLOBAL, &Globals.announce_as, NULL, enum_announce_as,  FLAG_ADVANCED}, 
989        {"map acl inherit", P_BOOL, P_LOCAL, &sDefault.bMap_acl_inherit, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
990        {"afs share", P_BOOL, P_LOCAL, &sDefault.bAfs_Share, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL},
991        {"max mux", P_INTEGER, P_GLOBAL, &Globals.max_mux, NULL, NULL, FLAG_ADVANCED}, 
992        {"max xmit", P_INTEGER, P_GLOBAL, &Globals.max_xmit, NULL, NULL, FLAG_ADVANCED}, 
993
994        {"name resolve order", P_STRING, P_GLOBAL, &Globals.szNameResolveOrder, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD}, 
995        {"max ttl", P_INTEGER, P_GLOBAL, &Globals.max_ttl, NULL, NULL, FLAG_ADVANCED}, 
996        {"max wins ttl", P_INTEGER, P_GLOBAL, &Globals.max_wins_ttl, NULL, NULL, FLAG_ADVANCED}, 
997        {"min wins ttl", P_INTEGER, P_GLOBAL, &Globals.min_wins_ttl, NULL, NULL, FLAG_ADVANCED}, 
998        {"time server", P_BOOL, P_GLOBAL, &Globals.bTimeServer, NULL, NULL, FLAG_ADVANCED}, 
999        {"unix extensions", P_BOOL, P_GLOBAL, &Globals.bUnixExtensions, NULL, NULL, FLAG_ADVANCED}, 
1000        {"use spnego", P_BOOL, P_GLOBAL, &Globals.bUseSpnego, NULL, NULL, FLAG_ADVANCED}, 
1001        {"client signing", P_ENUM, P_GLOBAL, &Globals.client_signing, NULL, enum_smb_signing_vals, FLAG_ADVANCED}, 
1002        {"server signing", P_ENUM, P_GLOBAL, &Globals.server_signing, NULL, enum_smb_signing_vals, FLAG_ADVANCED}, 
1003        {"client use spnego", P_BOOL, P_GLOBAL, &Globals.bClientUseSpnego, NULL, NULL, FLAG_ADVANCED}, 
1004
1005        {"enable asu support", P_BOOL, P_GLOBAL, &Globals.bASUSupport, NULL, NULL, FLAG_ADVANCED}, 
1006        {"svcctl list", P_LIST, P_GLOBAL, &Globals.szServicesList, NULL, NULL, FLAG_ADVANCED},
1007
1008        {N_("Tuning Options"), P_SEP, P_SEPARATOR}, 
1009
1010        {"block size", P_INTEGER, P_LOCAL, &sDefault.iBlock_size, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1011        {"deadtime", P_INTEGER, P_GLOBAL, &Globals.deadtime, NULL, NULL, FLAG_ADVANCED}, 
1012        {"getwd cache", P_BOOL, P_GLOBAL, &use_getwd_cache, NULL, NULL, FLAG_ADVANCED}, 
1013        {"keepalive", P_INTEGER, P_GLOBAL, &keepalive, NULL, NULL, FLAG_ADVANCED}, 
1014        {"change notify", P_BOOL, P_LOCAL, &sDefault.bChangeNotify, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE },
1015        {"kernel change notify", P_BOOL, P_LOCAL, &sDefault.bKernelChangeNotify, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE },
1016
1017        {"lpq cache time", P_INTEGER, P_GLOBAL, &Globals.lpqcachetime, NULL, NULL, FLAG_ADVANCED}, 
1018        {"max smbd processes", P_INTEGER, P_GLOBAL, &Globals.iMaxSmbdProcesses, NULL, NULL, FLAG_ADVANCED}, 
1019        {"max connections", P_INTEGER, P_LOCAL, &sDefault.iMaxConnections, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
1020        {"paranoid server security", P_BOOL, P_GLOBAL, &Globals.paranoid_server_security, NULL, NULL, FLAG_ADVANCED}, 
1021        {"max disk size", P_INTEGER, P_GLOBAL, &Globals.maxdisksize, NULL, NULL, FLAG_ADVANCED}, 
1022        {"max open files", P_INTEGER, P_GLOBAL, &Globals.max_open_files, NULL, NULL, FLAG_ADVANCED}, 
1023        {"min print space", P_INTEGER, P_LOCAL, &sDefault.iMinPrintSpace, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT}, 
1024        {"open files database hash size", P_INTEGER, P_GLOBAL, &Globals.open_files_db_hash_size, NULL, NULL, FLAG_ADVANCED}, 
1025
1026        {"socket options", P_GSTRING, P_GLOBAL, user_socket_options, NULL, NULL, FLAG_ADVANCED}, 
1027        {"strict allocate", P_BOOL, P_LOCAL, &sDefault.bStrictAllocate, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
1028        {"strict sync", P_BOOL, P_LOCAL, &sDefault.bStrictSync, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
1029        {"sync always", P_BOOL, P_LOCAL, &sDefault.bSyncAlways, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
1030        {"use mmap", P_BOOL, P_GLOBAL, &Globals.bUseMmap, NULL, NULL, FLAG_ADVANCED}, 
1031        {"use sendfile", P_BOOL, P_LOCAL, &sDefault.bUseSendfile, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
1032        {"hostname lookups", P_BOOL, P_GLOBAL, &Globals.bHostnameLookups, NULL, NULL, FLAG_ADVANCED}, 
1033        {"write cache size", P_INTEGER, P_LOCAL, &sDefault.iWriteCacheSize, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_DEPRECATED}, 
1034
1035        {"name cache timeout", P_INTEGER, P_GLOBAL, &Globals.name_cache_timeout, NULL, NULL, FLAG_ADVANCED}, 
1036
1037        {N_("Printing Options"), P_SEP, P_SEPARATOR}, 
1038
1039        {"max reported print jobs", P_INTEGER, P_LOCAL, &sDefault.iMaxReportedPrintJobs, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT}, 
1040        {"max print jobs", P_INTEGER, P_LOCAL, &sDefault.iMaxPrintJobs, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT}, 
1041        {"load printers", P_BOOL, P_GLOBAL, &Globals.bLoadPrinters, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT}, 
1042        {"printcap cache time", P_INTEGER, P_GLOBAL, &Globals.PrintcapCacheTime, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT}, 
1043        {"printcap name", P_STRING, P_GLOBAL, &Globals.szPrintcapname, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT}, 
1044        {"printcap", P_STRING, P_GLOBAL, &Globals.szPrintcapname, NULL, NULL, FLAG_HIDE}, 
1045        {"printable", P_BOOL, P_LOCAL, &sDefault.bPrint_ok, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT}, 
1046        {"print ok", P_BOOL, P_LOCAL, &sDefault.bPrint_ok, NULL, NULL, FLAG_HIDE}, 
1047        {"printing", P_ENUM, P_LOCAL, &sDefault.iPrinting, handle_printing, enum_printing, FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL}, 
1048        {"cups options", P_STRING, P_LOCAL, &sDefault.szCupsOptions, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL}, 
1049        {"cups server", P_STRING, P_GLOBAL, &Globals.szCupsServer, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL}, 
1050        {"iprint server", P_STRING, P_GLOBAL, &Globals.szIPrintServer, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL}, 
1051        {"print command", P_STRING, P_LOCAL, &sDefault.szPrintcommand, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL}, 
1052        {"disable spoolss", P_BOOL, P_GLOBAL, &Globals.bDisableSpoolss, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL}, 
1053        {"enable spoolss", P_BOOLREV, P_GLOBAL, &Globals.bDisableSpoolss, NULL, NULL, FLAG_HIDE}, 
1054        {"lpq command", P_STRING, P_LOCAL, &sDefault.szLpqcommand, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL}, 
1055        {"lprm command", P_STRING, P_LOCAL, &sDefault.szLprmcommand, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL}, 
1056        {"lppause command", P_STRING, P_LOCAL, &sDefault.szLppausecommand, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL}, 
1057        {"lpresume command", P_STRING, P_LOCAL, &sDefault.szLpresumecommand, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL}, 
1058        {"queuepause command", P_STRING, P_LOCAL, &sDefault.szQueuepausecommand, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL}, 
1059        {"queueresume command", P_STRING, P_LOCAL, &sDefault.szQueueresumecommand, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL}, 
1060
1061        {"addport command", P_STRING, P_GLOBAL, &Globals.szAddPortCommand, NULL, NULL, FLAG_ADVANCED}, 
1062        {"enumports command", P_STRING, P_GLOBAL, &Globals.szEnumPortsCommand, NULL, NULL, FLAG_ADVANCED}, 
1063        {"addprinter command", P_STRING, P_GLOBAL, &Globals.szAddPrinterCommand, NULL, NULL, FLAG_ADVANCED}, 
1064        {"deleteprinter command", P_STRING, P_GLOBAL, &Globals.szDeletePrinterCommand, NULL, NULL, FLAG_ADVANCED}, 
1065        {"show add printer wizard", P_BOOL, P_GLOBAL, &Globals.bMsAddPrinterWizard, NULL, NULL, FLAG_ADVANCED}, 
1066        {"os2 driver map", P_STRING, P_GLOBAL, &Globals.szOs2DriverMap, NULL, NULL, FLAG_ADVANCED}, 
1067
1068        {"printer name", P_STRING, P_LOCAL, &sDefault.szPrintername, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT}, 
1069        {"printer", P_STRING, P_LOCAL, &sDefault.szPrintername, NULL, NULL, FLAG_HIDE}, 
1070        {"use client driver", P_BOOL, P_LOCAL, &sDefault.bUseClientDriver, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT}, 
1071        {"default devmode", P_BOOL, P_LOCAL, &sDefault.bDefaultDevmode, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT}, 
1072        {"force printername", P_BOOL, P_LOCAL, &sDefault.bForcePrintername, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT}, 
1073        {"printjob username", P_STRING, P_LOCAL, &sDefault.szPrintjobUsername, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT},
1074
1075        {N_("Filename Handling"), P_SEP, P_SEPARATOR}, 
1076        {"mangling method", P_STRING, P_GLOBAL, &Globals.szManglingMethod, NULL, NULL, FLAG_ADVANCED}, 
1077        {"mangle prefix", P_INTEGER, P_GLOBAL, &Globals.mangle_prefix, NULL, NULL, FLAG_ADVANCED}, 
1078
1079        {"default case", P_ENUM, P_LOCAL, &sDefault.iDefaultCase, NULL, enum_case, FLAG_ADVANCED | FLAG_SHARE}, 
1080        {"case sensitive", P_ENUM, P_LOCAL, &sDefault.iCaseSensitive, NULL, enum_bool_auto, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1081        {"casesignames", P_ENUM, P_LOCAL, &sDefault.iCaseSensitive, NULL, enum_bool_auto, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL | FLAG_HIDE}, 
1082        {"preserve case", P_BOOL, P_LOCAL, &sDefault.bCasePreserve, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1083        {"short preserve case", P_BOOL, P_LOCAL, &sDefault.bShortCasePreserve, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1084        {"mangling char", P_CHAR, P_LOCAL, &sDefault.magic_char, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1085        {"hide dot files", P_BOOL, P_LOCAL, &sDefault.bHideDotFiles, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1086        {"hide special files", P_BOOL, P_LOCAL, &sDefault.bHideSpecialFiles, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1087        {"hide unreadable", P_BOOL, P_LOCAL, &sDefault.bHideUnReadable, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1088        {"hide unwriteable files", P_BOOL, P_LOCAL, &sDefault.bHideUnWriteableFiles, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1089        {"delete veto files", P_BOOL, P_LOCAL, &sDefault.bDeleteVetoFiles, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1090        {"veto files", P_STRING, P_LOCAL, &sDefault.szVetoFiles, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL }, 
1091        {"hide files", P_STRING, P_LOCAL, &sDefault.szHideFiles, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL }, 
1092        {"veto oplock files", P_STRING, P_LOCAL, &sDefault.szVetoOplockFiles, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL }, 
1093        {"map archive", P_BOOL, P_LOCAL, &sDefault.bMap_archive, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1094        {"map hidden", P_BOOL, P_LOCAL, &sDefault.bMap_hidden, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1095        {"map system", P_BOOL, P_LOCAL, &sDefault.bMap_system, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1096        {"map readonly", P_ENUM, P_LOCAL, &sDefault.iMap_readonly, NULL, enum_map_readonly, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1097        {"mangled names", P_BOOL, P_LOCAL, &sDefault.bMangledNames, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1098        {"mangled map", P_STRING, P_LOCAL, &sDefault.szMangledMap, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL | FLAG_DEPRECATED }, 
1099        {"max stat cache size", P_INTEGER, P_GLOBAL, &Globals.iMaxStatCacheSize, NULL, NULL, FLAG_ADVANCED}, 
1100        {"stat cache", P_BOOL, P_GLOBAL, &Globals.bStatCache, NULL, NULL, FLAG_ADVANCED}, 
1101        {"store dos attributes", P_BOOL, P_LOCAL, &sDefault.bStoreDosAttributes, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1102        {"dmapi support", P_BOOL, P_LOCAL, &sDefault.bDmapiSupport, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL},
1103
1104
1105        {N_("Domain Options"), P_SEP, P_SEPARATOR}, 
1106
1107        {"machine password timeout", P_INTEGER, P_GLOBAL, &Globals.machine_password_timeout, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD}, 
1108
1109        {N_("Logon Options"), P_SEP, P_SEPARATOR}, 
1110
1111        {"add user script", P_STRING, P_GLOBAL, &Globals.szAddUserScript, NULL, NULL, FLAG_ADVANCED}, 
1112        {"rename user script", P_STRING, P_GLOBAL, &Globals.szRenameUserScript, NULL, NULL, FLAG_ADVANCED},
1113        {"delete user script", P_STRING, P_GLOBAL, &Globals.szDelUserScript, NULL, NULL, FLAG_ADVANCED}, 
1114        {"add group script", P_STRING, P_GLOBAL, &Globals.szAddGroupScript, NULL, NULL, FLAG_ADVANCED}, 
1115        {"delete group script", P_STRING, P_GLOBAL, &Globals.szDelGroupScript, NULL, NULL, FLAG_ADVANCED}, 
1116        {"add user to group script", P_STRING, P_GLOBAL, &Globals.szAddUserToGroupScript, NULL, NULL, FLAG_ADVANCED}, 
1117        {"delete user from group script", P_STRING, P_GLOBAL, &Globals.szDelUserFromGroupScript, NULL, NULL, FLAG_ADVANCED}, 
1118        {"set primary group script", P_STRING, P_GLOBAL, &Globals.szSetPrimaryGroupScript, NULL, NULL, FLAG_ADVANCED}, 
1119        {"add machine script", P_STRING, P_GLOBAL, &Globals.szAddMachineScript, NULL, NULL, FLAG_ADVANCED}, 
1120        {"shutdown script", P_STRING, P_GLOBAL, &Globals.szShutdownScript, NULL, NULL, FLAG_ADVANCED}, 
1121        {"abort shutdown script", P_STRING, P_GLOBAL, &Globals.szAbortShutdownScript, NULL, NULL, FLAG_ADVANCED}, 
1122        {"username map script", P_STRING, P_GLOBAL, &Globals.szUsernameMapScript, NULL, NULL, FLAG_ADVANCED}, 
1123
1124        {"logon script", P_STRING, P_GLOBAL, &Globals.szLogonScript, NULL, NULL, FLAG_ADVANCED}, 
1125        {"logon path", P_STRING, P_GLOBAL, &Globals.szLogonPath, NULL, NULL, FLAG_ADVANCED}, 
1126        {"logon drive", P_STRING, P_GLOBAL, &Globals.szLogonDrive, NULL, NULL, FLAG_ADVANCED}, 
1127        {"logon home", P_STRING, P_GLOBAL, &Globals.szLogonHome, NULL, NULL, FLAG_ADVANCED}, 
1128        {"domain logons", P_BOOL, P_GLOBAL, &Globals.bDomainLogons, NULL, NULL, FLAG_ADVANCED}, 
1129
1130        {N_("Browse Options"), P_SEP, P_SEPARATOR}, 
1131
1132        {"os level", P_INTEGER, P_GLOBAL, &Globals.os_level, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED}, 
1133        {"lm announce", P_ENUM, P_GLOBAL, &Globals.lm_announce, NULL, enum_bool_auto, FLAG_ADVANCED}, 
1134        {"lm interval", P_INTEGER, P_GLOBAL, &Globals.lm_interval, NULL, NULL, FLAG_ADVANCED}, 
1135        {"preferred master", P_ENUM, P_GLOBAL, &Globals.bPreferredMaster, NULL, enum_bool_auto, FLAG_BASIC | FLAG_ADVANCED}, 
1136        {"prefered master", P_ENUM, P_GLOBAL, &Globals.bPreferredMaster, NULL, enum_bool_auto, FLAG_HIDE}, 
1137        {"local master", P_BOOL, P_GLOBAL, &Globals.bLocalMaster, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED}, 
1138        {"domain master", P_ENUM, P_GLOBAL, &Globals.bDomainMaster, NULL, enum_bool_auto, FLAG_BASIC | FLAG_ADVANCED}, 
1139        {"browse list", P_BOOL, P_GLOBAL, &Globals.bBrowseList, NULL, NULL, FLAG_ADVANCED}, 
1140        {"browseable", P_BOOL, P_LOCAL, &sDefault.bBrowseable, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT}, 
1141        {"browsable", P_BOOL, P_LOCAL, &sDefault.bBrowseable, NULL, NULL, FLAG_HIDE}, 
1142        {"enhanced browsing", P_BOOL, P_GLOBAL, &Globals.enhanced_browsing, NULL, NULL, FLAG_ADVANCED}, 
1143
1144        {N_("WINS Options"), P_SEP, P_SEPARATOR}, 
1145
1146        {"dns proxy", P_BOOL, P_GLOBAL, &Globals.bDNSproxy, NULL, NULL, FLAG_ADVANCED}, 
1147        {"wins proxy", P_BOOL, P_GLOBAL, &Globals.bWINSproxy, NULL, NULL, FLAG_ADVANCED}, 
1148
1149        {"wins server", P_LIST, P_GLOBAL, &Globals.szWINSservers, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD}, 
1150        {"wins support", P_BOOL, P_GLOBAL, &Globals.bWINSsupport, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD}, 
1151        {"wins hook", P_STRING, P_GLOBAL, &Globals.szWINSHook, NULL, NULL, FLAG_ADVANCED}, 
1152
1153        {N_("Locking Options"), P_SEP, P_SEPARATOR}, 
1154
1155        {"blocking locks", P_BOOL, P_LOCAL, &sDefault.bBlockingLocks, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1156        {"csc policy", P_ENUM, P_LOCAL, &sDefault.iCSCPolicy, NULL, enum_csc_policy, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1157        {"fake oplocks", P_BOOL, P_LOCAL, &sDefault.bFakeOplocks, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
1158        {"kernel oplocks", P_BOOL, P_GLOBAL, &Globals.bKernelOplocks, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL}, 
1159        {"locking", P_BOOL, P_LOCAL, &sDefault.bLocking, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1160        {"lock spin time", P_INTEGER, P_GLOBAL, &Globals.iLockSpinTime, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL}, 
1161
1162        {"oplocks", P_BOOL, P_LOCAL, &sDefault.bOpLocks, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1163        {"level2 oplocks", P_BOOL, P_LOCAL, &sDefault.bLevel2OpLocks, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1164        {"oplock break wait time", P_INTEGER, P_GLOBAL, &Globals.oplock_break_wait_time, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL}, 
1165        {"oplock contention limit", P_INTEGER, P_LOCAL, &sDefault.iOplockContentionLimit, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1166        {"posix locking", P_BOOL, P_LOCAL, &sDefault.bPosixLocking, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1167        {"strict locking", P_ENUM, P_LOCAL, &sDefault.iStrictLocking, NULL, enum_bool_auto, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1168        {"share modes", P_BOOL, P_LOCAL,  &sDefault.bShareModes, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1169
1170        {N_("Ldap Options"), P_SEP, P_SEPARATOR}, 
1171
1172        {"ldap admin dn", P_STRING, P_GLOBAL, &Globals.szLdapAdminDn, NULL, NULL, FLAG_ADVANCED}, 
1173        {"ldap delete dn", P_BOOL, P_GLOBAL, &Globals.ldap_delete_dn, NULL, NULL, FLAG_ADVANCED}, 
1174        {"ldap group suffix", P_STRING, P_GLOBAL, &Globals.szLdapGroupSuffix, NULL, NULL, FLAG_ADVANCED}, 
1175        {"ldap idmap suffix", P_STRING, P_GLOBAL, &Globals.szLdapIdmapSuffix, NULL, NULL, FLAG_ADVANCED}, 
1176        {"ldap machine suffix", P_STRING, P_GLOBAL, &Globals.szLdapMachineSuffix, NULL, NULL, FLAG_ADVANCED}, 
1177        {"ldap passwd sync", P_ENUM, P_GLOBAL, &Globals.ldap_passwd_sync, NULL, enum_ldap_passwd_sync, FLAG_ADVANCED}, 
1178        {"ldap password sync", P_ENUM, P_GLOBAL, &Globals.ldap_passwd_sync, NULL, enum_ldap_passwd_sync, FLAG_HIDE}, 
1179        {"ldap replication sleep", P_INTEGER, P_GLOBAL, &Globals.ldap_replication_sleep, NULL, NULL, FLAG_ADVANCED},
1180        {"ldap suffix", P_STRING, P_GLOBAL, &Globals.szLdapSuffix, NULL, NULL, FLAG_ADVANCED}, 
1181        {"ldap ssl", P_ENUM, P_GLOBAL, &Globals.ldap_ssl, NULL, enum_ldap_ssl, FLAG_ADVANCED}, 
1182        {"ldap timeout", P_INTEGER, P_GLOBAL, &Globals.ldap_timeout, NULL, NULL, FLAG_ADVANCED},
1183        {"ldap page size", P_INTEGER, P_GLOBAL, &Globals.ldap_page_size, NULL, NULL, FLAG_ADVANCED},
1184        {"ldap user suffix", P_STRING, P_GLOBAL, &Globals.szLdapUserSuffix, NULL, NULL, FLAG_ADVANCED}, 
1185
1186        {N_("Miscellaneous Options"), P_SEP, P_SEPARATOR}, 
1187        {"add share command", P_STRING, P_GLOBAL, &Globals.szAddShareCommand, NULL, NULL, FLAG_ADVANCED}, 
1188        {"change share command", P_STRING, P_GLOBAL, &Globals.szChangeShareCommand, NULL, NULL, FLAG_ADVANCED}, 
1189        {"delete share command", P_STRING, P_GLOBAL, &Globals.szDeleteShareCommand, NULL, NULL, FLAG_ADVANCED}, 
1190
1191        {N_("EventLog Options"), P_SEP, P_SEPARATOR}, 
1192        {"eventlog list",  P_LIST, P_GLOBAL, &Globals.szEventLogs, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, 
1193       
1194        {"config file", P_STRING, P_GLOBAL, &Globals.szConfigFile, NULL, NULL, FLAG_HIDE}, 
1195        {"preload", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL, NULL, FLAG_ADVANCED}, 
1196        {"auto services", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL, NULL, FLAG_ADVANCED}, 
1197        {"lock directory", P_STRING, P_GLOBAL, &Globals.szLockDir, NULL, NULL, FLAG_ADVANCED}, 
1198        {"lock dir", P_STRING, P_GLOBAL, &Globals.szLockDir, NULL, NULL, FLAG_HIDE}, 
1199        {"pid directory", P_STRING, P_GLOBAL, &Globals.szPidDir, NULL, NULL, FLAG_ADVANCED}, 
1200#ifdef WITH_UTMP
1201        {"utmp directory", P_STRING, P_GLOBAL, &Globals.szUtmpDir, NULL, NULL, FLAG_ADVANCED}, 
1202        {"wtmp directory", P_STRING, P_GLOBAL, &Globals.szWtmpDir, NULL, NULL, FLAG_ADVANCED}, 
1203        {"utmp", P_BOOL, P_GLOBAL, &Globals.bUtmp, NULL, NULL, FLAG_ADVANCED}, 
1204#endif
1205
1206        {"default service", P_STRING, P_GLOBAL, &Globals.szDefaultService, NULL, NULL, FLAG_ADVANCED}, 
1207        {"default", P_STRING, P_GLOBAL, &Globals.szDefaultService, NULL, NULL, FLAG_ADVANCED}, 
1208        {"message command", P_STRING, P_GLOBAL, &Globals.szMsgCommand, NULL, NULL, FLAG_ADVANCED}, 
1209        {"dfree cache time", P_INTEGER, P_LOCAL, &sDefault.iDfreeCacheTime, NULL, NULL, FLAG_ADVANCED}, 
1210        {"dfree command", P_STRING, P_LOCAL, &sDefault.szDfree, NULL, NULL, FLAG_ADVANCED}, 
1211        {"get quota command", P_STRING, P_GLOBAL, &Globals.szGetQuota, NULL, NULL, FLAG_ADVANCED}, 
1212        {"set quota command", P_STRING, P_GLOBAL, &Globals.szSetQuota, NULL, NULL, FLAG_ADVANCED}, 
1213        {"remote announce", P_STRING, P_GLOBAL, &Globals.szRemoteAnnounce, NULL, NULL, FLAG_ADVANCED}, 
1214        {"remote browse sync", P_STRING, P_GLOBAL, &Globals.szRemoteBrowseSync, NULL, NULL, FLAG_ADVANCED}, 
1215        {"socket address", P_STRING, P_GLOBAL, &Globals.szSocketAddress, NULL, NULL, FLAG_ADVANCED}, 
1216        {"homedir map", P_STRING, P_GLOBAL, &Globals.szNISHomeMapName, NULL, NULL, FLAG_ADVANCED}, 
1217        {"afs username map", P_STRING, P_GLOBAL, &Globals.szAfsUsernameMap, NULL, NULL, FLAG_ADVANCED}, 
1218        {"afs token lifetime", P_INTEGER, P_GLOBAL, &Globals.iAfsTokenLifetime, NULL, NULL, FLAG_ADVANCED},
1219        {"log nt token command", P_STRING, P_GLOBAL, &Globals.szLogNtTokenCommand, NULL, NULL, FLAG_ADVANCED},
1220        {"time offset", P_INTEGER, P_GLOBAL, &extra_time_offset, NULL, NULL, FLAG_ADVANCED}, 
1221        {"NIS homedir", P_BOOL, P_GLOBAL, &Globals.bNISHomeMap, NULL, NULL, FLAG_ADVANCED}, 
1222        {"-valid", P_BOOL, P_LOCAL, &sDefault.valid, NULL, NULL, FLAG_HIDE}, 
1223
1224        {"copy", P_STRING, P_LOCAL, &sDefault.szCopy, handle_copy, NULL, FLAG_HIDE}, 
1225        {"include", P_STRING, P_LOCAL, &sDefault.szInclude, handle_include, NULL, FLAG_HIDE}, 
1226        {"preexec", P_STRING, P_LOCAL, &sDefault.szPreExec, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT}, 
1227        {"exec", P_STRING, P_LOCAL, &sDefault.szPreExec, NULL, NULL, FLAG_ADVANCED}, 
1228
1229        {"preexec close", P_BOOL, P_LOCAL, &sDefault.bPreexecClose, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
1230        {"postexec", P_STRING, P_LOCAL, &sDefault.szPostExec, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT}, 
1231        {"root preexec", P_STRING, P_LOCAL, &sDefault.szRootPreExec, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT}, 
1232        {"root preexec close", P_BOOL, P_LOCAL, &sDefault.bRootpreexecClose, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
1233        {"root postexec", P_STRING, P_LOCAL, &sDefault.szRootPostExec, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT}, 
1234        {"available", P_BOOL, P_LOCAL, &sDefault.bAvailable, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT}, 
1235        {"usershare allow guests", P_BOOL, P_GLOBAL, &Globals.bUsershareAllowGuests, NULL, NULL, FLAG_ADVANCED},
1236        {"usershare max shares", P_INTEGER, P_GLOBAL, &Globals.iUsershareMaxShares, NULL, NULL, FLAG_ADVANCED},
1237        {"usershare owner only", P_BOOL, P_GLOBAL, &Globals.bUsershareOwnerOnly, NULL, NULL, FLAG_ADVANCED}, 
1238        {"usershare path", P_STRING, P_GLOBAL, &Globals.szUsersharePath, NULL, NULL, FLAG_ADVANCED},
1239        {"usershare prefix allow list", P_LIST, P_GLOBAL, &Globals.szUsersharePrefixAllowList, NULL, NULL, FLAG_ADVANCED}, 
1240        {"usershare prefix deny list", P_LIST, P_GLOBAL, &Globals.szUsersharePrefixDenyList, NULL, NULL, FLAG_ADVANCED}, 
1241        {"usershare template share", P_STRING, P_GLOBAL, &Globals.szUsershareTemplateShare, NULL, NULL, FLAG_ADVANCED},
1242        {"volume", P_STRING, P_LOCAL, &sDefault.volume, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE }, 
1243        {"fstype", P_STRING, P_LOCAL, &sDefault.fstype, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
1244        {"set directory", P_BOOLREV, P_LOCAL, &sDefault.bNo_set_dir, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
1245        {"wide links", P_BOOL, P_LOCAL, &sDefault.bWidelinks, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1246        {"follow symlinks", P_BOOL, P_LOCAL, &sDefault.bSymlinks, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1247        {"dont descend", P_STRING, P_LOCAL, &sDefault.szDontdescend, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
1248        {"magic script", P_STRING, P_LOCAL, &sDefault.szMagicScript, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
1249        {"magic output", P_STRING, P_LOCAL, &sDefault.szMagicOutput, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
1250        {"delete readonly", P_BOOL, P_LOCAL, &sDefault.bDeleteReadonly, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1251        {"dos filemode", P_BOOL, P_LOCAL, &sDefault.bDosFilemode, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1252        {"dos filetimes", P_BOOL, P_LOCAL, &sDefault.bDosFiletimes, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1253        {"dos filetime resolution", P_BOOL, P_LOCAL, &sDefault.bDosFiletimeResolution, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1254
1255        {"fake directory create times", P_BOOL, P_LOCAL, &sDefault.bFakeDirCreateTimes, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1256        {"panic action", P_STRING, P_GLOBAL, &Globals.szPanicAction, NULL, NULL, FLAG_ADVANCED}, 
1257
1258        {N_("VFS module options"), P_SEP, P_SEPARATOR}, 
1259
1260        {"vfs objects", P_LIST, P_LOCAL, &sDefault.szVfsObjects, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
1261        {"vfs object", P_LIST, P_LOCAL, &sDefault.szVfsObjects, NULL, NULL, FLAG_HIDE}, 
1262
1263
1264        {"msdfs root", P_BOOL, P_LOCAL, &sDefault.bMSDfsRoot, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
1265        {"msdfs proxy", P_STRING, P_LOCAL, &sDefault.szMSDfsProxy, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
1266        {"host msdfs", P_BOOL, P_GLOBAL, &Globals.bHostMSDfs, NULL, NULL, FLAG_ADVANCED}, 
1267
1268        {N_("Winbind options"), P_SEP, P_SEPARATOR}, 
1269
1270        {"passdb expand explicit", P_BOOL, P_GLOBAL, &Globals.bPassdbExpandExplicit, NULL, NULL, FLAG_ADVANCED},
1271        {"idmap domains", P_LIST, P_GLOBAL, &Globals.szIdmapDomains, NULL, NULL, FLAG_ADVANCED}, 
1272        {"idmap backend", P_LIST, P_GLOBAL, &Globals.szIdmapBackend, NULL, NULL, FLAG_ADVANCED }, 
1273        {"idmap alloc backend", P_STRING, P_GLOBAL, &Globals.szIdmapAllocBackend, NULL, NULL, FLAG_ADVANCED}, 
1274        {"idmap cache time", P_INTEGER, P_GLOBAL, &Globals.iIdmapCacheTime, NULL, NULL, FLAG_ADVANCED}, 
1275        {"idmap negative cache time", P_INTEGER, P_GLOBAL, &Globals.iIdmapNegativeCacheTime, NULL, NULL, FLAG_ADVANCED}, 
1276        {"idmap uid", P_STRING, P_GLOBAL, &Globals.szIdmapUID, handle_idmap_uid, NULL, FLAG_ADVANCED }, 
1277        {"winbind uid", P_STRING, P_GLOBAL, &Globals.szIdmapUID, handle_idmap_uid, NULL, FLAG_HIDE }, 
1278        {"idmap gid", P_STRING, P_GLOBAL, &Globals.szIdmapGID, handle_idmap_gid, NULL, FLAG_ADVANCED }, 
1279        {"winbind gid", P_STRING, P_GLOBAL, &Globals.szIdmapGID, handle_idmap_gid, NULL, FLAG_HIDE }, 
1280        {"template homedir", P_STRING, P_GLOBAL, &Globals.szTemplateHomedir, NULL, NULL, FLAG_ADVANCED}, 
1281        {"template shell", P_STRING, P_GLOBAL, &Globals.szTemplateShell, NULL, NULL, FLAG_ADVANCED}, 
1282        {"winbind separator", P_STRING, P_GLOBAL, &Globals.szWinbindSeparator, NULL, NULL, FLAG_ADVANCED}, 
1283        {"winbind cache time", P_INTEGER, P_GLOBAL, &Globals.winbind_cache_time, NULL, NULL, FLAG_ADVANCED}, 
1284        {"winbind enum users", P_BOOL, P_GLOBAL, &Globals.bWinbindEnumUsers, NULL, NULL, FLAG_ADVANCED}, 
1285        {"winbind enum groups", P_BOOL, P_GLOBAL, &Globals.bWinbindEnumGroups, NULL, NULL, FLAG_ADVANCED}, 
1286        {"winbind use default domain", P_BOOL, P_GLOBAL, &Globals.bWinbindUseDefaultDomain, NULL, NULL, FLAG_ADVANCED}, 
1287        {"winbind trusted domains only", P_BOOL, P_GLOBAL, &Globals.bWinbindTrustedDomainsOnly, NULL, NULL, FLAG_ADVANCED}, 
1288        {"winbind nested groups", P_BOOL, P_GLOBAL, &Globals.bWinbindNestedGroups, NULL, NULL, FLAG_ADVANCED}, 
1289        {"winbind nss info", P_LIST, P_GLOBAL, &Globals.szWinbindNssInfo, NULL, NULL, FLAG_ADVANCED}, 
1290        {"winbind refresh tickets", P_BOOL, P_GLOBAL, &Globals.bWinbindRefreshTickets, NULL, NULL, FLAG_ADVANCED}, 
1291        {"winbind offline logon", P_BOOL, P_GLOBAL, &Globals.bWinbindOfflineLogon, NULL, NULL, FLAG_ADVANCED},
1292        {"winbind normalize names", P_BOOL, P_GLOBAL, &Globals.bWinbindNormalizeNames, NULL, NULL, FLAG_ADVANCED},
1293
1294        {NULL,  P_BOOL,  P_NONE,  NULL,  NULL,  NULL,  0}
1295};
1296
1297/***************************************************************************
1298 Initialise the sDefault parameter structure for the printer values.
1299***************************************************************************/
1300
1301static void init_printer_values(service *pService)
1302{
1303        /* choose defaults depending on the type of printing */
1304        switch (pService->iPrinting) {
1305                case PRINT_BSD:
1306                case PRINT_AIX:
1307                case PRINT_LPRNT:
1308                case PRINT_LPROS2:
1309                        string_set(&pService->szLpqcommand, "lpq -P'%p'");
1310                        string_set(&pService->szLprmcommand, "lprm -P'%p' %j");
1311                        string_set(&pService->szPrintcommand, "lpr -r -P'%p' %s");
1312                        break;
1313
1314                case PRINT_LPRNG:
1315                case PRINT_PLP:
1316                        string_set(&pService->szLpqcommand, "lpq -P'%p'");
1317                        string_set(&pService->szLprmcommand, "lprm -P'%p' %j");
1318                        string_set(&pService->szPrintcommand, "lpr -r -P'%p' %s");
1319                        string_set(&pService->szQueuepausecommand, "lpc stop '%p'");
1320                        string_set(&pService->szQueueresumecommand, "lpc start '%p'");
1321                        string_set(&pService->szLppausecommand, "lpc hold '%p' %j");
1322                        string_set(&pService->szLpresumecommand, "lpc release '%p' %j");
1323                        break;
1324
1325                case PRINT_CUPS:
1326                case PRINT_IPRINT:
1327#ifdef HAVE_CUPS
1328                        /* set the lpq command to contain the destination printer
1329                           name only.  This is used by cups_queue_get() */
1330                        string_set(&pService->szLpqcommand, "%p");
1331                        string_set(&pService->szLprmcommand, "");
1332                        string_set(&pService->szPrintcommand, "");
1333                        string_set(&pService->szLppausecommand, "");
1334                        string_set(&pService->szLpresumecommand, "");
1335                        string_set(&pService->szQueuepausecommand, "");
1336                        string_set(&pService->szQueueresumecommand, "");
1337#else
1338                        string_set(&pService->szLpqcommand, "lpq -P'%p'");
1339                        string_set(&pService->szLprmcommand, "lprm -P'%p' %j");
1340                        string_set(&pService->szPrintcommand, "lpr -P'%p' %s; rm %s");
1341                        string_set(&pService->szLppausecommand, "lp -i '%p-%j' -H hold");
1342                        string_set(&pService->szLpresumecommand, "lp -i '%p-%j' -H resume");
1343                        string_set(&pService->szQueuepausecommand, "disable '%p'");
1344                        string_set(&pService->szQueueresumecommand, "enable '%p'");
1345#endif /* HAVE_CUPS */
1346                        break;
1347
1348                case PRINT_SYSV:
1349                case PRINT_HPUX:
1350                        string_set(&pService->szLpqcommand, "lpstat -o%p");
1351                        string_set(&pService->szLprmcommand, "cancel %p-%j");
1352                        string_set(&pService->szPrintcommand, "lp -c -d%p %s; rm %s");
1353                        string_set(&pService->szQueuepausecommand, "disable %p");
1354                        string_set(&pService->szQueueresumecommand, "enable %p");
1355#ifndef HPUX
1356                        string_set(&pService->szLppausecommand, "lp -i %p-%j -H hold");
1357                        string_set(&pService->szLpresumecommand, "lp -i %p-%j -H resume");
1358#endif /* HPUX */
1359                        break;
1360
1361                case PRINT_QNX:
1362                        string_set(&pService->szLpqcommand, "lpq -P%p");
1363                        string_set(&pService->szLprmcommand, "lprm -P%p %j");
1364                        string_set(&pService->szPrintcommand, "lp -r -P%p %s");
1365                        break;
1366
1367#ifdef DEVELOPER
1368        case PRINT_TEST:
1369        case PRINT_VLP:
1370                string_set(&pService->szPrintcommand, "vlp print %p %s");
1371                string_set(&pService->szLpqcommand, "vlp lpq %p");
1372                string_set(&pService->szLprmcommand, "vlp lprm %p %j");
1373                string_set(&pService->szLppausecommand, "vlp lppause %p %j");
1374                string_set(&pService->szLpresumecommand, "vlp lpresum %p %j");
1375                string_set(&pService->szQueuepausecommand, "vlp queuepause %p");
1376                string_set(&pService->szQueueresumecommand, "vlp queueresume %p");
1377                break;
1378#endif /* DEVELOPER */
1379
1380        }
1381}
1382
1383/***************************************************************************
1384 Initialise the global parameter structure.
1385***************************************************************************/
1386
1387#ifndef __OS2__
1388static 
1389#endif
1390void init_globals(BOOL first_time_only)
1391{
1392        static BOOL done_init = False;
1393        pstring s;
1394
1395        /* If requested to initialize only once and we've already done it... */
1396        if (first_time_only && done_init) {
1397                /* ... then we have nothing more to do */
1398                return;
1399        }
1400
1401        if (!done_init) {
1402                int i;
1403
1404                /* The logfile can be set before this is invoked. Free it if so. */
1405                if (Globals.szLogFile != NULL) {
1406                        string_free(&Globals.szLogFile);
1407                        Globals.szLogFile = NULL;
1408                }
1409
1410                memset((void *)&Globals, '\0', sizeof(Globals));
1411
1412                for (i = 0; parm_table[i].label; i++)
1413                        if ((parm_table[i].type == P_STRING ||
1414                             parm_table[i].type == P_USTRING) &&
1415                            parm_table[i].ptr)
1416                                string_set((char **)parm_table[i].ptr, "");
1417
1418                string_set(&sDefault.fstype, FSTYPE_STRING);
1419                string_set(&sDefault.szPrintjobUsername, "%U");
1420
1421                init_printer_values(&sDefault);
1422
1423                done_init = True;
1424        }
1425
1426
1427        DEBUG(3, ("Initialising global parameters\n"));
1428
1429        string_set(&Globals.szSMBPasswdFile, dyn_SMB_PASSWD_FILE);
1430        string_set(&Globals.szPrivateDir, dyn_PRIVATE_DIR);
1431
1432        /* use the new 'hash2' method by default, with a prefix of 1 */
1433        string_set(&Globals.szManglingMethod, "hash2");
1434        Globals.mangle_prefix = 1;
1435
1436        string_set(&Globals.szGuestaccount, GUEST_ACCOUNT);
1437
1438#ifndef __OS2__
1439        /* using UTF8 by default allows us to support all chars */
1440        string_set(&Globals.unix_charset, DEFAULT_UNIX_CHARSET);
1441#else
1442        /* On OS/2, using UTF8 causes problems with display of foreign characters - default to SYSTEM codepage */
1443        string_set(&Globals.unix_charset, "SYSTEM");
1444#endif
1445
1446#if defined(HAVE_NL_LANGINFO) && defined(CODESET)
1447        /* If the system supports nl_langinfo(), try to grab the value
1448           from the user's locale */
1449        string_set(&Globals.display_charset, "LOCALE");
1450#else
1451        string_set(&Globals.display_charset, DEFAULT_DISPLAY_CHARSET);
1452#endif
1453
1454        /* Use codepage 850 as a default for the dos character set */
1455        string_set(&Globals.dos_charset, DEFAULT_DOS_CHARSET);
1456
1457        /*
1458         * Allow the default PASSWD_CHAT to be overridden in local.h.
1459         */
1460        string_set(&Globals.szPasswdChat, DEFAULT_PASSWD_CHAT);
1461       
1462        set_global_myname(myhostname());
1463        string_set(&Globals.szNetbiosName,global_myname());
1464
1465        set_global_myworkgroup(WORKGROUP);
1466        string_set(&Globals.szWorkgroup, lp_workgroup());
1467       
1468        string_set(&Globals.szPasswdProgram, "");
1469        string_set(&Globals.szPidDir, dyn_PIDDIR);
1470        string_set(&Globals.szLockDir, dyn_LOCKDIR);
1471        string_set(&Globals.szSocketAddress, "0.0.0.0");
1472        pstrcpy(s, "Samba ");
1473        pstrcat(s, SAMBA_VERSION_STRING);
1474        string_set(&Globals.szServerString, s);
1475        slprintf(s, sizeof(s) - 1, "%d.%d", DEFAULT_MAJOR_VERSION,
1476                 DEFAULT_MINOR_VERSION);
1477        string_set(&Globals.szAnnounceVersion, s);
1478#ifdef DEVELOPER
1479        string_set(&Globals.szPanicAction, "/bin/sleep 999999999");
1480#endif
1481
1482        pstrcpy(user_socket_options, DEFAULT_SOCKET_OPTIONS);
1483
1484        string_set(&Globals.szLogonDrive, "");
1485        /* %N is the NIS auto.home server if -DAUTOHOME is used, else same as %L */
1486        string_set(&Globals.szLogonHome, "\\\\%N\\%U");
1487        string_set(&Globals.szLogonPath, "\\\\%N\\%U\\profile");
1488
1489        string_set(&Globals.szNameResolveOrder, "lmhosts wins host bcast");
1490        string_set(&Globals.szPasswordServer, "*");
1491
1492        Globals.AlgorithmicRidBase = BASE_RID;
1493
1494        Globals.bLoadPrinters = True;
1495        Globals.PrintcapCacheTime = 750;        /* 12.5 minutes */
1496
1497        /* Was 65535 (0xFFFF). 0x4101 matches W2K and causes major speed improvements... */
1498        /* Discovered by 2 days of pain by Don McCall @ HP :-). */
1499        Globals.max_xmit = 0x4104;
1500        Globals.max_mux = 50;   /* This is *needed* for profile support. */
1501        Globals.lpqcachetime = 30;      /* changed to handle large print servers better -- jerry */
1502        Globals.bDisableSpoolss = False;
1503        Globals.iMaxSmbdProcesses = 0;/* no limit specified */
1504        Globals.pwordlevel = 0;
1505        Globals.unamelevel = 0;
1506        Globals.deadtime = 0;
1507        Globals.bLargeReadwrite = True;
1508        Globals.max_log_size = 5000;
1509        Globals.max_open_files = MAX_OPEN_FILES;
1510        Globals.open_files_db_hash_size = SMB_OPEN_DATABASE_TDB_HASH_SIZE;
1511        Globals.maxprotocol = PROTOCOL_NT1;
1512        Globals.minprotocol = PROTOCOL_CORE;
1513        Globals.security = SEC_USER;
1514        Globals.paranoid_server_security = True;
1515        Globals.bEncryptPasswords = True;
1516        Globals.bUpdateEncrypt = False;
1517        Globals.clientSchannel = Auto;
1518        Globals.serverSchannel = Auto;
1519        Globals.bReadRaw = True;
1520        Globals.bWriteRaw = True;
1521        Globals.bReadbmpx = False;
1522        Globals.bNullPasswords = False;
1523        Globals.bObeyPamRestrictions = False;
1524        Globals.syslog = 1;
1525        Globals.bSyslogOnly = False;
1526        Globals.bTimestampLogs = True;
1527        string_set(&Globals.szLogLevel, "0");
1528        Globals.bDebugPrefixTimestamp = False;
1529        Globals.bDebugHiresTimestamp = False;
1530        Globals.bDebugPid = False;
1531        Globals.bDebugUid = False;
1532        Globals.bEnableCoreFiles = True;
1533        Globals.max_ttl = 60 * 60 * 24 * 3;     /* 3 days default. */
1534        Globals.max_wins_ttl = 60 * 60 * 24 * 6;        /* 6 days default. */
1535        Globals.min_wins_ttl = 60 * 60 * 6;     /* 6 hours default. */
1536        Globals.machine_password_timeout = 60 * 60 * 24 * 7;    /* 7 days default. */
1537        Globals.lm_announce = 2;        /* = Auto: send only if LM clients found */
1538        Globals.lm_interval = 60;
1539        Globals.announce_as = ANNOUNCE_AS_NT_SERVER;
1540#if (defined(HAVE_NETGROUP) && defined(WITH_AUTOMOUNT))
1541        Globals.bNISHomeMap = False;
1542#ifdef WITH_NISPLUS_HOME
1543        string_set(&Globals.szNISHomeMapName, "auto_home.org_dir");
1544#else
1545        string_set(&Globals.szNISHomeMapName, "auto.home");
1546#endif
1547#endif
1548        Globals.bTimeServer = False;
1549        Globals.bBindInterfacesOnly = False;
1550        Globals.bUnixPasswdSync = False;
1551        Globals.bPamPasswordChange = False;
1552        Globals.bPasswdChatDebug = False;
1553        Globals.iPasswdChatTimeout = 2; /* 2 second default. */
1554        Globals.bNTPipeSupport = True;  /* Do NT pipes by default. */
1555        Globals.bNTStatusSupport = True; /* Use NT status by default. */
1556        Globals.bStatCache = True;      /* use stat cache by default */
1557        Globals.iMaxStatCacheSize = 1024; /* one Meg by default. */
1558        Globals.restrict_anonymous = 0;
1559        Globals.bClientLanManAuth = True;       /* Do use the LanMan hash if it is available */
1560        Globals.bClientPlaintextAuth = True;    /* Do use a plaintext password if is requested by the server */
1561        Globals.bLanmanAuth = True;     /* Do use the LanMan hash if it is available */
1562        Globals.bNTLMAuth = True;       /* Do use NTLMv1 if it is available (otherwise NTLMv2) */
1563        Globals.bClientNTLMv2Auth = False; /* Client should not use NTLMv2, as we can't tell that the server supports it. */
1564        /* Note, that we will use NTLM2 session security (which is different), if it is available */
1565
1566        Globals.map_to_guest = 0;       /* By Default, "Never" */
1567        Globals.oplock_break_wait_time = 0;     /* By Default, 0 msecs. */
1568        Globals.enhanced_browsing = True; 
1569        Globals.iLockSpinTime = WINDOWS_MINIMUM_LOCK_TIMEOUT_MS; /* msec. */
1570#ifdef MMAP_BLACKLIST
1571        Globals.bUseMmap = False;
1572#else
1573        Globals.bUseMmap = True;
1574#endif
1575        Globals.bUnixExtensions = True;
1576        Globals.bResetOnZeroVC = False;
1577
1578        /* hostname lookups can be very expensive and are broken on
1579           a large number of sites (tridge) */
1580        Globals.bHostnameLookups = False;
1581
1582        string_set(&Globals.szPassdbBackend, "smbpasswd");
1583        string_set(&Globals.szLdapSuffix, "");
1584        string_set(&Globals.szLdapMachineSuffix, "");
1585        string_set(&Globals.szLdapUserSuffix, "");
1586        string_set(&Globals.szLdapGroupSuffix, "");
1587        string_set(&Globals.szLdapIdmapSuffix, "");
1588
1589        string_set(&Globals.szLdapAdminDn, "");
1590        Globals.ldap_ssl = LDAP_SSL_ON;
1591        Globals.ldap_passwd_sync = LDAP_PASSWD_SYNC_OFF;
1592        Globals.ldap_delete_dn = False;
1593        Globals.ldap_replication_sleep = 1000; /* wait 1 sec for replication */
1594        Globals.ldap_timeout = LDAP_CONNECT_DEFAULT_TIMEOUT;
1595        Globals.ldap_page_size = LDAP_PAGE_SIZE;
1596
1597        /* This is what we tell the afs client. in reality we set the token
1598         * to never expire, though, when this runs out the afs client will
1599         * forget the token. Set to 0 to get NEVERDATE.*/
1600        Globals.iAfsTokenLifetime = 604800;
1601
1602/* these parameters are set to defaults that are more appropriate
1603   for the increasing samba install base:
1604
1605   as a member of the workgroup, that will possibly become a
1606   _local_ master browser (lm = True).  this is opposed to a forced
1607   local master browser startup (pm = True).
1608
1609   doesn't provide WINS server service by default (wsupp = False),
1610   and doesn't provide domain master browser services by default, either.
1611
1612*/
1613
1614        Globals.bMsAddPrinterWizard = True;
1615        Globals.bPreferredMaster = Auto;        /* depending on bDomainMaster */
1616        Globals.os_level = 20;
1617        Globals.bLocalMaster = True;
1618        Globals.bDomainMaster = Auto;   /* depending on bDomainLogons */
1619        Globals.bDomainLogons = False;
1620        Globals.bBrowseList = True;
1621        Globals.bWINSsupport = False;
1622        Globals.bWINSproxy = False;
1623
1624        Globals.bDNSproxy = True;
1625
1626        /* this just means to use them if they exist */
1627        Globals.bKernelOplocks = True;
1628
1629        Globals.bAllowTrustedDomains = True;
1630
1631        string_set(&Globals.szTemplateShell, "/bin/false");
1632        string_set(&Globals.szTemplateHomedir, "/home/%D/%U");
1633        string_set(&Globals.szWinbindSeparator, "\\");
1634
1635        string_set(&Globals.szCupsServer, "");
1636        string_set(&Globals.szIPrintServer, "");
1637
1638        Globals.winbind_cache_time = 300;       /* 5 minutes */
1639        Globals.bWinbindEnumUsers = False;
1640        Globals.bWinbindEnumGroups = False;
1641        Globals.bWinbindUseDefaultDomain = False;
1642        Globals.bWinbindTrustedDomainsOnly = False;
1643        Globals.bWinbindNestedGroups = True;
1644        Globals.szWinbindNssInfo = str_list_make("template", NULL);
1645        Globals.bWinbindRefreshTickets = False;
1646        Globals.bWinbindOfflineLogon = False;
1647
1648        Globals.iIdmapCacheTime = 900; /* 15 minutes by default */
1649        Globals.iIdmapNegativeCacheTime = 120; /* 2 minutes by default */
1650
1651        Globals.bPassdbExpandExplicit = False;
1652
1653        Globals.name_cache_timeout = 660; /* In seconds */
1654
1655        Globals.bUseSpnego = True;
1656        Globals.bClientUseSpnego = True;
1657
1658        Globals.client_signing = Auto;
1659        Globals.server_signing = False;
1660
1661        Globals.bDeferSharingViolations = True;
1662        string_set(&Globals.smb_ports, SMB_PORTS);
1663
1664        Globals.bEnablePrivileges = True;
1665        Globals.bHostMSDfs        = True;
1666        Globals.bASUSupport       = False;
1667       
1668        /* User defined shares. */
1669        pstrcpy(s, dyn_LOCKDIR);
1670        pstrcat(s, "/usershares");
1671        string_set(&Globals.szUsersharePath, s);
1672        string_set(&Globals.szUsershareTemplateShare, "");
1673        Globals.iUsershareMaxShares = 0;
1674        /* By default disallow sharing of directories not owned by the sharer. */
1675        Globals.bUsershareOwnerOnly = True;
1676        /* By default disallow guest access to usershares. */
1677        Globals.bUsershareAllowGuests = False;
1678}
1679
1680static TALLOC_CTX *lp_talloc;
1681
1682/******************************************************************* a
1683 Free up temporary memory - called from the main loop.
1684********************************************************************/
1685
1686void lp_TALLOC_FREE(void)
1687{
1688        if (!lp_talloc)
1689                return;
1690        TALLOC_FREE(lp_talloc);
1691        lp_talloc = NULL;
1692}
1693
1694TALLOC_CTX *tmp_talloc_ctx(void)
1695{
1696        if (lp_talloc == NULL) {
1697                lp_talloc = talloc_init("tmp_talloc_ctx");
1698        }
1699
1700        if (lp_talloc == NULL) {
1701                smb_panic("Could not create temporary talloc context\n");
1702        }
1703
1704        return lp_talloc;
1705}
1706
1707/*******************************************************************
1708 Convenience routine to grab string parameters into temporary memory
1709 and run standard_sub_basic on them. The buffers can be written to by
1710 callers without affecting the source string.
1711********************************************************************/
1712
1713static char *lp_string(const char *s)
1714{
1715        char *ret, *tmpstr;
1716
1717        /* The follow debug is useful for tracking down memory problems
1718           especially if you have an inner loop that is calling a lp_*()
1719           function that returns a string.  Perhaps this debug should be
1720           present all the time? */
1721
1722#if 0
1723        DEBUG(10, ("lp_string(%s)\n", s));
1724#endif
1725
1726        if (!lp_talloc)
1727                lp_talloc = talloc_init("lp_talloc");
1728
1729        tmpstr = alloc_sub_basic(get_current_username(),
1730                                 current_user_info.domain, s);
1731        if (trim_char(tmpstr, '\"', '\"')) {
1732                if (strchr(tmpstr,'\"') != NULL) {
1733                        SAFE_FREE(tmpstr);
1734                        tmpstr = alloc_sub_basic(get_current_username(),
1735                                                 current_user_info.domain, s);
1736                }
1737        }
1738        ret = talloc_strdup(lp_talloc, tmpstr);
1739        SAFE_FREE(tmpstr);
1740                       
1741        return (ret);
1742}
1743
1744/*
1745   In this section all the functions that are used to access the
1746   parameters from the rest of the program are defined
1747*/
1748
1749#define FN_GLOBAL_STRING(fn_name,ptr) \
1750 char *fn_name(void) {return(lp_string(*(char **)(ptr) ? *(char **)(ptr) : ""));}
1751#define FN_GLOBAL_CONST_STRING(fn_name,ptr) \
1752 const char *fn_name(void) {return(*(const char **)(ptr) ? *(const char **)(ptr) : "");}
1753#define FN_GLOBAL_LIST(fn_name,ptr) \
1754 const char **fn_name(void) {return(*(const char ***)(ptr));}
1755#define FN_GLOBAL_BOOL(fn_name,ptr) \
1756 BOOL fn_name(void) {return(*(BOOL *)(ptr));}
1757#define FN_GLOBAL_CHAR(fn_name,ptr) \
1758 char fn_name(void) {return(*(char *)(ptr));}
1759#define FN_GLOBAL_INTEGER(fn_name,ptr) \
1760 int fn_name(void) {return(*(int *)(ptr));}
1761
1762#define FN_LOCAL_STRING(fn_name,val) \
1763 char *fn_name(int i) {return(lp_string((LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val));}
1764#define FN_LOCAL_CONST_STRING(fn_name,val) \
1765 const char *fn_name(int i) {return (const char *)((LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val);}
1766#define FN_LOCAL_LIST(fn_name,val) \
1767 const char **fn_name(int i) {return(const char **)(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1768#define FN_LOCAL_BOOL(fn_name,val) \
1769 BOOL fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1770#define FN_LOCAL_INTEGER(fn_name,val) \
1771 int fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1772
1773#define FN_LOCAL_PARM_BOOL(fn_name,val) \
1774 BOOL fn_name(const struct share_params *p) {return(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
1775#define FN_LOCAL_PARM_INTEGER(fn_name,val) \
1776 int fn_name(const struct share_params *p) {return(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
1777#define FN_LOCAL_PARM_STRING(fn_name,val) \
1778 char *fn_name(const struct share_params *p) {return(lp_string((LP_SNUM_OK(p->service) && ServicePtrs[(p->service)]->val) ? ServicePtrs[(p->service)]->val : sDefault.val));}
1779#define FN_LOCAL_CHAR(fn_name,val) \
1780 char fn_name(const struct share_params *p) {return(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
1781
1782FN_GLOBAL_STRING(lp_smb_ports, &Globals.smb_ports)
1783FN_GLOBAL_STRING(lp_dos_charset, &Globals.dos_charset)
1784FN_GLOBAL_STRING(lp_unix_charset, &Globals.unix_charset)
1785FN_GLOBAL_STRING(lp_display_charset, &Globals.display_charset)
1786FN_GLOBAL_STRING(lp_logfile, &Globals.szLogFile)
1787FN_GLOBAL_STRING(lp_configfile, &Globals.szConfigFile)
1788FN_GLOBAL_STRING(lp_smb_passwd_file, &Globals.szSMBPasswdFile)
1789FN_GLOBAL_STRING(lp_private_dir, &Globals.szPrivateDir)
1790FN_GLOBAL_STRING(lp_serverstring, &Globals.szServerString)
1791FN_GLOBAL_INTEGER(lp_printcap_cache_time, &Globals.PrintcapCacheTime)
1792FN_GLOBAL_STRING(lp_addport_cmd, &Globals.szAddPortCommand)
1793FN_GLOBAL_STRING(lp_enumports_cmd, &Globals.szEnumPortsCommand)
1794FN_GLOBAL_STRING(lp_addprinter_cmd, &Globals.szAddPrinterCommand)
1795FN_GLOBAL_STRING(lp_deleteprinter_cmd, &Globals.szDeletePrinterCommand)
1796FN_GLOBAL_STRING(lp_os2_driver_map, &Globals.szOs2DriverMap)
1797FN_GLOBAL_STRING(lp_lockdir, &Globals.szLockDir)
1798FN_GLOBAL_STRING(lp_piddir, &Globals.szPidDir)
1799FN_GLOBAL_STRING(lp_mangling_method, &Globals.szManglingMethod)
1800FN_GLOBAL_INTEGER(lp_mangle_prefix, &Globals.mangle_prefix)
1801FN_GLOBAL_STRING(lp_utmpdir, &Globals.szUtmpDir)
1802FN_GLOBAL_STRING(lp_wtmpdir, &Globals.szWtmpDir)
1803FN_GLOBAL_BOOL(lp_utmp, &Globals.bUtmp)
1804FN_GLOBAL_STRING(lp_rootdir, &Globals.szRootdir)
1805FN_GLOBAL_STRING(lp_defaultservice, &Globals.szDefaultService)
1806FN_GLOBAL_STRING(lp_msg_command, &Globals.szMsgCommand)
1807FN_GLOBAL_STRING(lp_get_quota_command, &Globals.szGetQuota)
1808FN_GLOBAL_STRING(lp_set_quota_command, &Globals.szSetQuota)
1809FN_GLOBAL_STRING(lp_auto_services, &Globals.szAutoServices)
1810FN_GLOBAL_STRING(lp_passwd_program, &Globals.szPasswdProgram)
1811FN_GLOBAL_STRING(lp_passwd_chat, &Globals.szPasswdChat)
1812FN_GLOBAL_STRING(lp_passwordserver, &Globals.szPasswordServer)
1813FN_GLOBAL_STRING(lp_name_resolve_order, &Globals.szNameResolveOrder)
1814FN_GLOBAL_STRING(lp_realm, &Globals.szRealm)
1815FN_GLOBAL_CONST_STRING(lp_afs_username_map, &Globals.szAfsUsernameMap)
1816FN_GLOBAL_INTEGER(lp_afs_token_lifetime, &Globals.iAfsTokenLifetime)
1817FN_GLOBAL_STRING(lp_log_nt_token_command, &Globals.szLogNtTokenCommand)
1818FN_GLOBAL_STRING(lp_username_map, &Globals.szUsernameMap)
1819FN_GLOBAL_CONST_STRING(lp_logon_script, &Globals.szLogonScript)
1820FN_GLOBAL_CONST_STRING(lp_logon_path, &Globals.szLogonPath)
1821FN_GLOBAL_CONST_STRING(lp_logon_drive, &Globals.szLogonDrive)
1822FN_GLOBAL_CONST_STRING(lp_logon_home, &Globals.szLogonHome)
1823FN_GLOBAL_STRING(lp_remote_announce, &Globals.szRemoteAnnounce)
1824FN_GLOBAL_STRING(lp_remote_browse_sync, &Globals.szRemoteBrowseSync)
1825FN_GLOBAL_LIST(lp_wins_server_list, &Globals.szWINSservers)
1826FN_GLOBAL_LIST(lp_interfaces, &Globals.szInterfaces)
1827FN_GLOBAL_STRING(lp_socket_address, &Globals.szSocketAddress)
1828FN_GLOBAL_STRING(lp_nis_home_map_name, &Globals.szNISHomeMapName)
1829static FN_GLOBAL_STRING(lp_announce_version, &Globals.szAnnounceVersion)
1830FN_GLOBAL_LIST(lp_netbios_aliases, &Globals.szNetbiosAliases)
1831/* FN_GLOBAL_STRING(lp_passdb_backend, &Globals.szPassdbBackend)
1832 * lp_passdb_backend() should be replace by the this macro again after
1833 * some releases.
1834 * */
1835const char *lp_passdb_backend(void)
1836{
1837        char *delim, *quote;
1838
1839        delim = strchr( Globals.szPassdbBackend, ' ');
1840        /* no space at all */
1841        if (delim == NULL) {
1842                goto out;
1843        }
1844
1845        quote = strchr(Globals.szPassdbBackend, '"');
1846        /* no quote char or non in the first part */
1847        if (quote == NULL || quote > delim) {
1848                *delim = '\0';
1849                goto warn;
1850        }
1851
1852        quote = strchr(quote+1, '"');
1853        if (quote == NULL) {
1854                DEBUG(0, ("WARNING: Your 'passdb backend' configuration is invalid due to a missing second \" char.\n"));
1855                goto out;
1856        } else if (*(quote+1) == '\0') {
1857                /* space, fitting quote char, and one backend only */
1858                goto out;
1859        } else {
1860                /* terminate string after the fitting quote char */
1861                *(quote+1) = '\0';
1862        }
1863
1864warn:
1865        DEBUG(0, ("WARNING: Your 'passdb backend' configuration includes multiple backends.  This\n"
1866                "is deprecated since Samba 3.0.23.  Please check WHATSNEW.txt or the section 'Passdb\n"
1867                "Changes' from the ChangeNotes as part of the Samba HOWTO collection.  Only the first\n"
1868                "backend (%s) is used.  The rest is ignored.\n", Globals.szPassdbBackend));
1869
1870out:
1871        return Globals.szPassdbBackend;
1872}
1873FN_GLOBAL_LIST(lp_preload_modules, &Globals.szPreloadModules)
1874FN_GLOBAL_STRING(lp_panic_action, &Globals.szPanicAction)
1875FN_GLOBAL_STRING(lp_adduser_script, &Globals.szAddUserScript)
1876FN_GLOBAL_STRING(lp_renameuser_script, &Globals.szRenameUserScript)
1877FN_GLOBAL_STRING(lp_deluser_script, &Globals.szDelUserScript)
1878
1879FN_GLOBAL_CONST_STRING(lp_guestaccount, &Globals.szGuestaccount)
1880FN_GLOBAL_STRING(lp_addgroup_script, &Globals.szAddGroupScript)
1881FN_GLOBAL_STRING(lp_delgroup_script, &Globals.szDelGroupScript)
1882FN_GLOBAL_STRING(lp_addusertogroup_script, &Globals.szAddUserToGroupScript)
1883FN_GLOBAL_STRING(lp_deluserfromgroup_script, &Globals.szDelUserFromGroupScript)
1884FN_GLOBAL_STRING(lp_setprimarygroup_script, &Globals.szSetPrimaryGroupScript)
1885
1886FN_GLOBAL_STRING(lp_addmachine_script, &Globals.szAddMachineScript)
1887
1888FN_GLOBAL_STRING(lp_shutdown_script, &Globals.szShutdownScript)
1889FN_GLOBAL_STRING(lp_abort_shutdown_script, &Globals.szAbortShutdownScript)
1890FN_GLOBAL_STRING(lp_username_map_script, &Globals.szUsernameMapScript)
1891
1892FN_GLOBAL_STRING(lp_check_password_script, &Globals.szCheckPasswordScript)
1893
1894FN_GLOBAL_STRING(lp_wins_hook, &Globals.szWINSHook)
1895FN_GLOBAL_CONST_STRING(lp_template_homedir, &Globals.szTemplateHomedir)
1896FN_GLOBAL_CONST_STRING(lp_template_shell, &Globals.szTemplateShell)
1897FN_GLOBAL_CONST_STRING(lp_winbind_separator, &Globals.szWinbindSeparator)
1898FN_GLOBAL_INTEGER(lp_acl_compatibility, &Globals.iAclCompat)
1899FN_GLOBAL_BOOL(lp_winbind_enum_users, &Globals.bWinbindEnumUsers)
1900FN_GLOBAL_BOOL(lp_winbind_enum_groups, &Globals.bWinbindEnumGroups)
1901FN_GLOBAL_BOOL(lp_winbind_use_default_domain, &Globals.bWinbindUseDefaultDomain)
1902FN_GLOBAL_BOOL(lp_winbind_trusted_domains_only, &Globals.bWinbindTrustedDomainsOnly)
1903FN_GLOBAL_BOOL(lp_winbind_nested_groups, &Globals.bWinbindNestedGroups)
1904FN_GLOBAL_BOOL(lp_winbind_refresh_tickets, &Globals.bWinbindRefreshTickets)
1905FN_GLOBAL_BOOL(lp_winbind_offline_logon, &Globals.bWinbindOfflineLogon)
1906FN_GLOBAL_BOOL(lp_winbind_normalize_names, &Globals.bWinbindNormalizeNames)
1907
1908FN_GLOBAL_LIST(lp_idmap_domains, &Globals.szIdmapDomains)
1909FN_GLOBAL_LIST(lp_idmap_backend, &Globals.szIdmapBackend) /* deprecated */
1910FN_GLOBAL_STRING(lp_idmap_alloc_backend, &Globals.szIdmapAllocBackend)
1911FN_GLOBAL_INTEGER(lp_idmap_cache_time, &Globals.iIdmapCacheTime)
1912FN_GLOBAL_INTEGER(lp_idmap_negative_cache_time, &Globals.iIdmapNegativeCacheTime)
1913FN_GLOBAL_BOOL(lp_passdb_expand_explicit, &Globals.bPassdbExpandExplicit)
1914
1915FN_GLOBAL_STRING(lp_ldap_suffix, &Globals.szLdapSuffix)
1916FN_GLOBAL_STRING(lp_ldap_admin_dn, &Globals.szLdapAdminDn)
1917FN_GLOBAL_INTEGER(lp_ldap_ssl, &Globals.ldap_ssl)
1918FN_GLOBAL_INTEGER(lp_ldap_passwd_sync, &Globals.ldap_passwd_sync)
1919FN_GLOBAL_BOOL(lp_ldap_delete_dn, &Globals.ldap_delete_dn)
1920FN_GLOBAL_INTEGER(lp_ldap_replication_sleep, &Globals.ldap_replication_sleep)
1921FN_GLOBAL_INTEGER(lp_ldap_timeout, &Globals.ldap_timeout)
1922FN_GLOBAL_INTEGER(lp_ldap_page_size, &Globals.ldap_page_size)
1923FN_GLOBAL_STRING(lp_add_share_cmd, &Globals.szAddShareCommand)
1924FN_GLOBAL_STRING(lp_change_share_cmd, &Globals.szChangeShareCommand)
1925FN_GLOBAL_STRING(lp_delete_share_cmd, &Globals.szDeleteShareCommand)
1926FN_GLOBAL_STRING(lp_usershare_path, &Globals.szUsersharePath)
1927FN_GLOBAL_LIST(lp_usershare_prefix_allow_list, &Globals.szUsersharePrefixAllowList)
1928FN_GLOBAL_LIST(lp_usershare_prefix_deny_list, &Globals.szUsersharePrefixDenyList)
1929
1930FN_GLOBAL_LIST(lp_eventlog_list, &Globals.szEventLogs)
1931
1932FN_GLOBAL_BOOL(lp_usershare_allow_guests, &Globals.bUsershareAllowGuests)
1933FN_GLOBAL_BOOL(lp_usershare_owner_only, &Globals.bUsershareOwnerOnly)
1934FN_GLOBAL_BOOL(lp_disable_netbios, &Globals.bDisableNetbios)
1935FN_GLOBAL_BOOL(lp_reset_on_zero_vc, &Globals.bResetOnZeroVC)
1936FN_GLOBAL_BOOL(lp_ms_add_printer_wizard, &Globals.bMsAddPrinterWizard)
1937FN_GLOBAL_BOOL(lp_dns_proxy, &Globals.bDNSproxy)
1938FN_GLOBAL_BOOL(lp_wins_support, &Globals.bWINSsupport)
1939FN_GLOBAL_BOOL(lp_we_are_a_wins_server, &Globals.bWINSsupport)
1940FN_GLOBAL_BOOL(lp_wins_proxy, &Globals.bWINSproxy)
1941FN_GLOBAL_BOOL(lp_local_master, &Globals.bLocalMaster)
1942FN_GLOBAL_BOOL(lp_domain_logons, &Globals.bDomainLogons)
1943FN_GLOBAL_BOOL(lp_load_printers, &Globals.bLoadPrinters)
1944FN_GLOBAL_BOOL(lp_readbmpx, &Globals.bReadbmpx)
1945FN_GLOBAL_BOOL(lp_readraw, &Globals.bReadRaw)
1946FN_GLOBAL_BOOL(lp_large_readwrite, &Globals.bLargeReadwrite)
1947FN_GLOBAL_BOOL(lp_writeraw, &Globals.bWriteRaw)
1948FN_GLOBAL_BOOL(lp_null_passwords, &Globals.bNullPasswords)
1949FN_GLOBAL_BOOL(lp_obey_pam_restrictions, &Globals.bObeyPamRestrictions)
1950FN_GLOBAL_BOOL(lp_encrypted_passwords, &Globals.bEncryptPasswords)
1951FN_GLOBAL_BOOL(lp_update_encrypted, &Globals.bUpdateEncrypt)
1952FN_GLOBAL_INTEGER(lp_client_schannel, &Globals.clientSchannel)
1953FN_GLOBAL_INTEGER(lp_server_schannel, &Globals.serverSchannel)
1954FN_GLOBAL_BOOL(lp_syslog_only, &Globals.bSyslogOnly)
1955FN_GLOBAL_BOOL(lp_timestamp_logs, &Globals.bTimestampLogs)
1956FN_GLOBAL_BOOL(lp_debug_prefix_timestamp, &Globals.bDebugPrefixTimestamp)
1957FN_GLOBAL_BOOL(lp_debug_hires_timestamp, &Globals.bDebugHiresTimestamp)
1958FN_GLOBAL_BOOL(lp_debug_pid, &Globals.bDebugPid)
1959FN_GLOBAL_BOOL(lp_debug_uid, &Globals.bDebugUid)
1960FN_GLOBAL_BOOL(lp_enable_core_files, &Globals.bEnableCoreFiles)
1961FN_GLOBAL_BOOL(lp_browse_list, &Globals.bBrowseList)
1962FN_GLOBAL_BOOL(lp_nis_home_map, &Globals.bNISHomeMap)
1963static FN_GLOBAL_BOOL(lp_time_server, &Globals.bTimeServer)
1964FN_GLOBAL_BOOL(lp_bind_interfaces_only, &Globals.bBindInterfacesOnly)
1965FN_GLOBAL_BOOL(lp_pam_password_change, &Globals.bPamPasswordChange)
1966FN_GLOBAL_BOOL(lp_unix_password_sync, &Globals.bUnixPasswdSync)
1967FN_GLOBAL_BOOL(lp_passwd_chat_debug, &Globals.bPasswdChatDebug)
1968FN_GLOBAL_INTEGER(lp_passwd_chat_timeout, &Globals.iPasswdChatTimeout)
1969FN_GLOBAL_BOOL(lp_nt_pipe_support, &Globals.bNTPipeSupport)
1970FN_GLOBAL_BOOL(lp_nt_status_support, &Globals.bNTStatusSupport)
1971FN_GLOBAL_BOOL(lp_stat_cache, &Globals.bStatCache)
1972FN_GLOBAL_INTEGER(lp_max_stat_cache_size, &Globals.iMaxStatCacheSize)
1973FN_GLOBAL_BOOL(lp_allow_trusted_domains, &Globals.bAllowTrustedDomains)
1974FN_GLOBAL_INTEGER(lp_restrict_anonymous, &Globals.restrict_anonymous)
1975FN_GLOBAL_BOOL(lp_lanman_auth, &Globals.bLanmanAuth)
1976FN_GLOBAL_BOOL(lp_ntlm_auth, &Globals.bNTLMAuth)
1977FN_GLOBAL_BOOL(lp_client_plaintext_auth, &Globals.bClientPlaintextAuth)
1978FN_GLOBAL_BOOL(lp_client_lanman_auth, &Globals.bClientLanManAuth)
1979FN_GLOBAL_BOOL(lp_client_ntlmv2_auth, &Globals.bClientNTLMv2Auth)
1980FN_GLOBAL_BOOL(lp_host_msdfs, &Globals.bHostMSDfs)
1981FN_GLOBAL_BOOL(lp_kernel_oplocks, &Globals.bKernelOplocks)
1982FN_GLOBAL_BOOL(lp_enhanced_browsing, &Globals.enhanced_browsing)
1983FN_GLOBAL_BOOL(lp_use_mmap, &Globals.bUseMmap)
1984FN_GLOBAL_BOOL(lp_unix_extensions, &Globals.bUnixExtensions)
1985FN_GLOBAL_BOOL(lp_use_spnego, &Globals.bUseSpnego)
1986FN_GLOBAL_BOOL(lp_client_use_spnego, &Globals.bClientUseSpnego)
1987FN_GLOBAL_BOOL(lp_hostname_lookups, &Globals.bHostnameLookups)
1988FN_LOCAL_PARM_BOOL(lp_change_notify, bChangeNotify)
1989FN_LOCAL_PARM_BOOL(lp_kernel_change_notify, bKernelChangeNotify)
1990FN_GLOBAL_BOOL(lp_use_kerberos_keytab, &Globals.bUseKerberosKeytab)
1991FN_GLOBAL_BOOL(lp_defer_sharing_violations, &Globals.bDeferSharingViolations)
1992FN_GLOBAL_BOOL(lp_enable_privileges, &Globals.bEnablePrivileges)
1993FN_GLOBAL_BOOL(lp_enable_asu_support, &Globals.bASUSupport)
1994FN_GLOBAL_INTEGER(lp_os_level, &Globals.os_level)
1995FN_GLOBAL_INTEGER(lp_max_ttl, &Globals.max_ttl)
1996FN_GLOBAL_INTEGER(lp_max_wins_ttl, &Globals.max_wins_ttl)
1997FN_GLOBAL_INTEGER(lp_min_wins_ttl, &Globals.min_wins_ttl)
1998FN_GLOBAL_INTEGER(lp_max_log_size, &Globals.max_log_size)
1999FN_GLOBAL_INTEGER(lp_max_open_files, &Globals.max_open_files)
2000FN_GLOBAL_INTEGER(lp_open_files_db_hash_size, &Globals.open_files_db_hash_size)
2001FN_GLOBAL_INTEGER(lp_maxxmit, &Globals.max_xmit)
2002FN_GLOBAL_INTEGER(lp_maxmux, &Globals.max_mux)
2003FN_GLOBAL_INTEGER(lp_passwordlevel, &Globals.pwordlevel)
2004FN_GLOBAL_INTEGER(lp_usernamelevel, &Globals.unamelevel)
2005FN_GLOBAL_INTEGER(lp_deadtime, &Globals.deadtime)
2006FN_GLOBAL_INTEGER(lp_maxprotocol, &Globals.maxprotocol)
2007FN_GLOBAL_INTEGER(lp_minprotocol, &Globals.minprotocol)
2008FN_GLOBAL_INTEGER(lp_security, &Globals.security)
2009FN_GLOBAL_LIST(lp_auth_methods, &Globals.AuthMethods)
2010FN_GLOBAL_BOOL(lp_paranoid_server_security, &Globals.paranoid_server_security)
2011FN_GLOBAL_INTEGER(lp_maxdisksize, &Globals.maxdisksize)
2012FN_GLOBAL_INTEGER(lp_lpqcachetime, &Globals.lpqcachetime)
2013FN_GLOBAL_INTEGER(lp_max_smbd_processes, &Globals.iMaxSmbdProcesses)
2014FN_GLOBAL_INTEGER(_lp_disable_spoolss, &Globals.bDisableSpoolss)
2015FN_GLOBAL_INTEGER(lp_syslog, &Globals.syslog)
2016static FN_GLOBAL_INTEGER(lp_announce_as, &Globals.announce_as)
2017FN_GLOBAL_INTEGER(lp_lm_announce, &Globals.lm_announce)
2018FN_GLOBAL_INTEGER(lp_lm_interval, &Globals.lm_interval)
2019FN_GLOBAL_INTEGER(lp_machine_password_timeout, &Globals.machine_password_timeout)
2020FN_GLOBAL_INTEGER(lp_map_to_guest, &Globals.map_to_guest)
2021FN_GLOBAL_INTEGER(lp_oplock_break_wait_time, &Globals.oplock_break_wait_time)
2022FN_GLOBAL_INTEGER(lp_lock_spin_time, &Globals.iLockSpinTime)
2023FN_GLOBAL_INTEGER(lp_usershare_max_shares, &Globals.iUsershareMaxShares)
2024
2025FN_LOCAL_STRING(lp_preexec, szPreExec)
2026FN_LOCAL_STRING(lp_postexec, szPostExec)
2027FN_LOCAL_STRING(lp_rootpreexec, szRootPreExec)
2028FN_LOCAL_STRING(lp_rootpostexec, szRootPostExec)
2029FN_LOCAL_STRING(lp_servicename, szService)
2030FN_LOCAL_CONST_STRING(lp_const_servicename, szService)
2031FN_LOCAL_STRING(lp_pathname, szPath)
2032FN_LOCAL_STRING(lp_dontdescend, szDontdescend)
2033FN_LOCAL_STRING(lp_username, szUsername)
2034FN_LOCAL_LIST(lp_invalid_users, szInvalidUsers)
2035FN_LOCAL_LIST(lp_valid_users, szValidUsers)
2036FN_LOCAL_LIST(lp_admin_users, szAdminUsers)
2037FN_GLOBAL_LIST(lp_svcctl_list, &Globals.szServicesList)
2038FN_LOCAL_STRING(lp_cups_options, szCupsOptions)
2039FN_GLOBAL_STRING(lp_cups_server, &Globals.szCupsServer)
2040FN_GLOBAL_STRING(lp_iprint_server, &Globals.szIPrintServer)
2041FN_LOCAL_STRING(lp_printcommand, szPrintcommand)
2042FN_LOCAL_STRING(lp_lpqcommand, szLpqcommand)
2043FN_LOCAL_STRING(lp_lprmcommand, szLprmcommand)
2044FN_LOCAL_STRING(lp_lppausecommand, szLppausecommand)
2045FN_LOCAL_STRING(lp_lpresumecommand, szLpresumecommand)
2046FN_LOCAL_STRING(lp_queuepausecommand, szQueuepausecommand)
2047FN_LOCAL_STRING(lp_queueresumecommand, szQueueresumecommand)
2048static FN_LOCAL_STRING(_lp_printername, szPrintername)
2049FN_LOCAL_CONST_STRING(lp_printjob_username, szPrintjobUsername)
2050FN_LOCAL_LIST(lp_hostsallow, szHostsallow)
2051FN_LOCAL_LIST(lp_hostsdeny, szHostsdeny)
2052FN_LOCAL_STRING(lp_magicscript, szMagicScript)
2053FN_LOCAL_STRING(lp_magicoutput, szMagicOutput)
2054FN_LOCAL_STRING(lp_comment, comment)
2055FN_LOCAL_STRING(lp_force_user, force_user)
2056FN_LOCAL_STRING(lp_force_group, force_group)
2057FN_LOCAL_LIST(lp_readlist, readlist)
2058FN_LOCAL_LIST(lp_writelist, writelist)
2059FN_LOCAL_LIST(lp_printer_admin, printer_admin)
2060FN_LOCAL_STRING(lp_fstype, fstype)
2061FN_LOCAL_LIST(lp_vfs_objects, szVfsObjects)
2062FN_LOCAL_STRING(lp_msdfs_proxy, szMSDfsProxy)
2063static FN_LOCAL_STRING(lp_volume, volume)
2064FN_LOCAL_PARM_STRING(lp_mangled_map, szMangledMap)
2065FN_LOCAL_STRING(lp_veto_files, szVetoFiles)
2066FN_LOCAL_STRING(lp_hide_files, szHideFiles)
2067FN_LOCAL_STRING(lp_veto_oplocks, szVetoOplockFiles)
2068FN_LOCAL_BOOL(lp_msdfs_root, bMSDfsRoot)
2069FN_LOCAL_STRING(lp_aio_write_behind, szAioWriteBehind)
2070FN_LOCAL_STRING(lp_dfree_command, szDfree)
2071FN_LOCAL_BOOL(lp_autoloaded, autoloaded)
2072FN_LOCAL_BOOL(lp_preexec_close, bPreexecClose)
2073FN_LOCAL_BOOL(lp_rootpreexec_close, bRootpreexecClose)
2074FN_LOCAL_INTEGER(lp_casesensitive, iCaseSensitive)
2075FN_LOCAL_BOOL(lp_preservecase, bCasePreserve)
2076FN_LOCAL_BOOL(lp_shortpreservecase, bShortCasePreserve)
2077FN_LOCAL_BOOL(lp_hide_dot_files, bHideDotFiles)
2078FN_LOCAL_BOOL(lp_hide_special_files, bHideSpecialFiles)
2079FN_LOCAL_BOOL(lp_hideunreadable, bHideUnReadable)
2080FN_LOCAL_BOOL(lp_hideunwriteable_files, bHideUnWriteableFiles)
2081FN_LOCAL_BOOL(lp_browseable, bBrowseable)
2082FN_LOCAL_BOOL(lp_readonly, bRead_only)
2083FN_LOCAL_BOOL(lp_no_set_dir, bNo_set_dir)
2084FN_LOCAL_BOOL(lp_guest_ok, bGuest_ok)
2085FN_LOCAL_BOOL(lp_guest_only, bGuest_only)
2086FN_LOCAL_BOOL(lp_print_ok, bPrint_ok)
2087FN_LOCAL_BOOL(lp_map_hidden, bMap_hidden)
2088FN_LOCAL_BOOL(lp_map_archive, bMap_archive)
2089FN_LOCAL_BOOL(lp_store_dos_attributes, bStoreDosAttributes)
2090FN_LOCAL_BOOL(lp_dmapi_support, bDmapiSupport)
2091FN_LOCAL_PARM_BOOL(lp_locking, bLocking)
2092FN_LOCAL_PARM_INTEGER(lp_strict_locking, iStrictLocking)
2093FN_LOCAL_PARM_BOOL(lp_posix_locking, bPosixLocking)
2094FN_LOCAL_BOOL(lp_share_modes, bShareModes)
2095FN_LOCAL_BOOL(lp_oplocks, bOpLocks)
2096FN_LOCAL_BOOL(lp_level2_oplocks, bLevel2OpLocks)
2097FN_LOCAL_BOOL(lp_onlyuser, bOnlyUser)
2098FN_LOCAL_PARM_BOOL(lp_manglednames, bMangledNames)
2099FN_LOCAL_BOOL(lp_widelinks, bWidelinks)
2100FN_LOCAL_BOOL(lp_symlinks, bSymlinks)
2101FN_LOCAL_BOOL(lp_syncalways, bSyncAlways)
2102FN_LOCAL_BOOL(lp_strict_allocate, bStrictAllocate)
2103FN_LOCAL_BOOL(lp_strict_sync, bStrictSync)
2104FN_LOCAL_BOOL(lp_map_system, bMap_system)
2105FN_LOCAL_BOOL(lp_delete_readonly, bDeleteReadonly)
2106FN_LOCAL_BOOL(lp_fake_oplocks, bFakeOplocks)
2107FN_LOCAL_BOOL(lp_recursive_veto_delete, bDeleteVetoFiles)
2108FN_LOCAL_BOOL(lp_dos_filemode, bDosFilemode)
2109FN_LOCAL_BOOL(lp_dos_filetimes, bDosFiletimes)
2110FN_LOCAL_BOOL(lp_dos_filetime_resolution, bDosFiletimeResolution)
2111FN_LOCAL_BOOL(lp_fake_dir_create_times, bFakeDirCreateTimes)
2112FN_LOCAL_BOOL(lp_blocking_locks, bBlockingLocks)
2113FN_LOCAL_BOOL(lp_inherit_perms, bInheritPerms)
2114FN_LOCAL_BOOL(lp_inherit_acls, bInheritACLS)
2115FN_LOCAL_BOOL(lp_inherit_owner, bInheritOwner)
2116FN_LOCAL_BOOL(lp_use_client_driver, bUseClientDriver)
2117FN_LOCAL_BOOL(lp_default_devmode, bDefaultDevmode)
2118FN_LOCAL_BOOL(lp_force_printername, bForcePrintername)
2119FN_LOCAL_BOOL(lp_nt_acl_support, bNTAclSupport)
2120FN_LOCAL_BOOL(lp_force_unknown_acl_user, bForceUnknownAclUser)
2121FN_LOCAL_BOOL(lp_ea_support, bEASupport)
2122FN_LOCAL_BOOL(_lp_use_sendfile, bUseSendfile)
2123FN_LOCAL_BOOL(lp_profile_acls, bProfileAcls)
2124FN_LOCAL_BOOL(lp_map_acl_inherit, bMap_acl_inherit)
2125FN_LOCAL_BOOL(lp_afs_share, bAfs_Share)
2126FN_LOCAL_BOOL(lp_acl_check_permissions, bAclCheckPermissions)
2127FN_LOCAL_BOOL(lp_acl_group_control, bAclGroupControl)
2128FN_LOCAL_BOOL(lp_acl_map_full_control, bAclMapFullControl)
2129FN_LOCAL_INTEGER(lp_create_mask, iCreate_mask)
2130FN_LOCAL_INTEGER(lp_force_create_mode, iCreate_force_mode)
2131FN_LOCAL_INTEGER(lp_security_mask, iSecurity_mask)
2132FN_LOCAL_INTEGER(lp_force_security_mode, iSecurity_force_mode)
2133FN_LOCAL_INTEGER(lp_dir_mask, iDir_mask)
2134FN_LOCAL_INTEGER(lp_force_dir_mode, iDir_force_mode)
2135FN_LOCAL_INTEGER(lp_dir_security_mask, iDir_Security_mask)
2136FN_LOCAL_INTEGER(lp_force_dir_security_mode, iDir_Security_force_mode)
2137FN_LOCAL_INTEGER(lp_max_connections, iMaxConnections)
2138FN_LOCAL_INTEGER(lp_defaultcase, iDefaultCase)
2139FN_LOCAL_INTEGER(lp_minprintspace, iMinPrintSpace)
2140FN_LOCAL_INTEGER(lp_printing, iPrinting)
2141FN_LOCAL_INTEGER(lp_max_reported_jobs, iMaxReportedPrintJobs)
2142FN_LOCAL_INTEGER(lp_oplock_contention_limit, iOplockContentionLimit)
2143FN_LOCAL_INTEGER(lp_csc_policy, iCSCPolicy)
2144FN_LOCAL_INTEGER(lp_write_cache_size, iWriteCacheSize)
2145FN_LOCAL_INTEGER(lp_block_size, iBlock_size)
2146FN_LOCAL_INTEGER(lp_dfree_cache_time, iDfreeCacheTime)
2147FN_LOCAL_INTEGER(lp_allocation_roundup_size, iallocation_roundup_size)
2148FN_LOCAL_INTEGER(lp_aio_read_size, iAioReadSize)
2149FN_LOCAL_INTEGER(lp_aio_write_size, iAioWriteSize)
2150FN_LOCAL_INTEGER(lp_map_readonly, iMap_readonly)
2151FN_LOCAL_CHAR(lp_magicchar, magic_char)
2152FN_GLOBAL_INTEGER(lp_winbind_cache_time, &Globals.winbind_cache_time)
2153FN_GLOBAL_LIST(lp_winbind_nss_info, &Globals.szWinbindNssInfo)
2154FN_GLOBAL_INTEGER(lp_algorithmic_rid_base, &Globals.AlgorithmicRidBase)
2155FN_GLOBAL_INTEGER(lp_name_cache_timeout, &Globals.name_cache_timeout)
2156FN_GLOBAL_INTEGER(lp_client_signing, &Globals.client_signing)
2157FN_GLOBAL_INTEGER(lp_server_signing, &Globals.server_signing)
2158
2159/* local prototypes */
2160
2161static int map_parameter(const char *pszParmName);
2162static BOOL set_boolean(BOOL *pb, const char *pszParmValue);
2163static int getservicebyname(const char *pszServiceName,
2164                            service * pserviceDest);
2165static void copy_service(service * pserviceDest,
2166                         service * pserviceSource, BOOL *pcopymapDest);
2167static BOOL service_ok(int iService);
2168static BOOL do_parameter(const char *pszParmName, const char *pszParmValue);
2169static BOOL do_section(const char *pszSectionName);
2170static void init_copymap(service * pservice);
2171static BOOL hash_a_service(const char *name, int number);
2172static void free_service_byindex(int iService);
2173static char * canonicalize_servicename(const char *name);
2174
2175/* This is a helper function for parametrical options support. */
2176/* It returns a pointer to parametrical option value if it exists or NULL otherwise */
2177/* Actual parametrical functions are quite simple */
2178static param_opt_struct *get_parametrics(int snum, const char *type, const char *option)
2179{
2180        BOOL global_section = False;
2181        char* param_key;
2182        param_opt_struct *data;
2183       
2184        if (snum >= iNumServices) return NULL;
2185       
2186        if (snum < 0) { 
2187                data = Globals.param_opt;
2188                global_section = True;
2189        } else {
2190                data = ServicePtrs[snum]->param_opt;
2191        }
2192   
2193        asprintf(&param_key, "%s:%s", type, option);
2194        if (!param_key) {
2195                DEBUG(0,("asprintf failed!\n"));
2196                return NULL;
2197        }
2198
2199        while (data) {
2200                if (strcmp(data->key, param_key) == 0) {
2201                        string_free(&param_key);
2202                        return data;
2203                }
2204                data = data->next;
2205        }
2206
2207        if (!global_section) {
2208                /* Try to fetch the same option but from globals */
2209                /* but only if we are not already working with Globals */
2210                data = Globals.param_opt;
2211                while (data) {
2212                        if (strcmp(data->key, param_key) == 0) {
2213                                string_free(&param_key);
2214                                return data;
2215                        }
2216                        data = data->next;
2217                }
2218        }
2219
2220        string_free(&param_key);
2221       
2222        return NULL;
2223}
2224
2225
2226#define MISSING_PARAMETER(name) \
2227    DEBUG(0, ("%s(): value is NULL or empty!\n", #name))
2228
2229/*******************************************************************
2230convenience routine to return int parameters.
2231********************************************************************/
2232static int lp_int(const char *s)
2233{
2234
2235        if (!s || !*s) {
2236                MISSING_PARAMETER(lp_int);
2237                return (-1);
2238        }
2239
2240        return (int)strtol(s, NULL, 0);
2241}
2242
2243/*******************************************************************
2244convenience routine to return unsigned long parameters.
2245********************************************************************/
2246static unsigned long lp_ulong(const char *s)
2247{
2248
2249        if (!s || !*s) {
2250                MISSING_PARAMETER(lp_ulong);
2251                return (0);
2252        }
2253
2254        return strtoul(s, NULL, 0);
2255}
2256
2257/*******************************************************************
2258convenience routine to return boolean parameters.
2259********************************************************************/
2260static BOOL lp_bool(const char *s)
2261{
2262        BOOL ret = False;
2263
2264        if (!s || !*s) {
2265                MISSING_PARAMETER(lp_bool);
2266                return False;
2267        }
2268       
2269        if (!set_boolean(&ret,s)) {
2270                DEBUG(0,("lp_bool(%s): value is not boolean!\n",s));
2271                return False;
2272        }
2273
2274        return ret;
2275}
2276
2277/*******************************************************************
2278convenience routine to return enum parameters.
2279********************************************************************/
2280static int lp_enum(const char *s,const struct enum_list *_enum)
2281{
2282        int i;
2283
2284        if (!s || !*s || !_enum) {
2285                MISSING_PARAMETER(lp_enum);
2286                return (-1);
2287        }
2288       
2289        for (i=0; _enum[i].name; i++) {
2290                if (strequal(_enum[i].name,s))
2291                        return _enum[i].value;
2292        }
2293
2294        DEBUG(0,("lp_enum(%s,enum): value is not in enum_list!\n",s));
2295        return (-1);
2296}
2297
2298#undef MISSING_PARAMETER
2299
2300/* DO NOT USE lp_parm_string ANYMORE!!!!
2301 * use lp_parm_const_string or lp_parm_talloc_string
2302 *
2303 * lp_parm_string is only used to let old modules find this symbol
2304 */
2305#undef lp_parm_string
2306 char *lp_parm_string(const char *servicename, const char *type, const char *option);
2307 char *lp_parm_string(const char *servicename, const char *type, const char *option)
2308{
2309        return lp_parm_talloc_string(lp_servicenumber(servicename), type, option, NULL);
2310}
2311
2312/* Return parametric option from a given service. Type is a part of option before ':' */
2313/* Parametric option has following syntax: 'Type: option = value' */
2314/* the returned value is talloced in lp_talloc */
2315char *lp_parm_talloc_string(int snum, const char *type, const char *option, const char *def)
2316{
2317        param_opt_struct *data = get_parametrics(snum, type, option);
2318       
2319        if (data == NULL||data->value==NULL) {
2320                if (def) {
2321                        return lp_string(def);
2322                } else {
2323                        return NULL;
2324                }
2325        }
2326
2327        return lp_string(data->value);
2328}
2329
2330/* Return parametric option from a given service. Type is a part of option before ':' */
2331/* Parametric option has following syntax: 'Type: option = value' */
2332const char *lp_parm_const_string(int snum, const char *type, const char *option, const char *def)
2333{
2334        param_opt_struct *data = get_parametrics(snum, type, option);
2335       
2336        if (data == NULL||data->value==NULL)
2337                return def;
2338               
2339        return data->value;
2340}
2341
2342/* Return parametric option from a given service. Type is a part of option before ':' */
2343/* Parametric option has following syntax: 'Type: option = value' */
2344
2345const char **lp_parm_string_list(int snum, const char *type, const char *option, const char **def)
2346{
2347        param_opt_struct *data = get_parametrics(snum, type, option);
2348
2349        if (data == NULL||data->value==NULL)
2350                return (const char **)def;
2351               
2352        if (data->list==NULL) {
2353                data->list = str_list_make(data->value, NULL);
2354        }
2355
2356        return (const char **)data->list;
2357}
2358
2359/* Return parametric option from a given service. Type is a part of option before ':' */
2360/* Parametric option has following syntax: 'Type: option = value' */
2361
2362int lp_parm_int(int snum, const char *type, const char *option, int def)
2363{
2364        param_opt_struct *data = get_parametrics(snum, type, option);
2365       
2366        if (data && data->value && *data->value)
2367                return lp_int(data->value);
2368
2369        return def;
2370}
2371
2372/* Return parametric option from a given service. Type is a part of option before ':' */
2373/* Parametric option has following syntax: 'Type: option = value' */
2374
2375unsigned long lp_parm_ulong(int snum, const char *type, const char *option, unsigned long def)
2376{
2377        param_opt_struct *data = get_parametrics(snum, type, option);
2378       
2379        if (data && data->value && *data->value)
2380                return lp_ulong(data->value);
2381
2382        return def;
2383}
2384
2385/* Return parametric option from a given service. Type is a part of option before ':' */
2386/* Parametric option has following syntax: 'Type: option = value' */
2387
2388BOOL lp_parm_bool(int snum, const char *type, const char *option, BOOL def)
2389{
2390        param_opt_struct *data = get_parametrics(snum, type, option);
2391       
2392        if (data && data->value && *data->value)
2393                return lp_bool(data->value);
2394
2395        return def;
2396}
2397
2398/* Return parametric option from a given service. Type is a part of option before ':' */
2399/* Parametric option has following syntax: 'Type: option = value' */
2400
2401int lp_parm_enum(int snum, const char *type, const char *option,
2402                 const struct enum_list *_enum, int def)
2403{
2404        param_opt_struct *data = get_parametrics(snum, type, option);
2405       
2406        if (data && data->value && *data->value && _enum)
2407                return lp_enum(data->value, _enum);
2408
2409        return def;
2410}
2411
2412
2413/***************************************************************************
2414 Initialise a service to the defaults.
2415***************************************************************************/
2416
2417static void init_service(service * pservice)
2418{
2419        memset((char *)pservice, '\0', sizeof(service));
2420        copy_service(pservice, &sDefault, NULL);
2421}
2422
2423/***************************************************************************
2424 Free the dynamically allocated parts of a service struct.
2425***************************************************************************/
2426
2427static void free_service(service *pservice)
2428{
2429        int i;
2430        param_opt_struct *data, *pdata;
2431        if (!pservice)
2432                return;
2433
2434        if (pservice->szService)
2435                DEBUG(5, ("free_service: Freeing service %s\n",
2436                       pservice->szService));
2437
2438        string_free(&pservice->szService);
2439        SAFE_FREE(pservice->copymap);
2440
2441        for (i = 0; parm_table[i].label; i++) {
2442                if ((parm_table[i].type == P_STRING ||
2443                     parm_table[i].type == P_USTRING) &&
2444                    parm_table[i].p_class == P_LOCAL)
2445                        string_free((char **)
2446                                    (((char *)pservice) +
2447                                     PTR_DIFF(parm_table[i].ptr, &sDefault)));
2448                else if (parm_table[i].type == P_LIST &&
2449                         parm_table[i].p_class == P_LOCAL)
2450                             str_list_free((char ***)
2451                                            (((char *)pservice) +
2452                                             PTR_DIFF(parm_table[i].ptr, &sDefault)));
2453        }
2454
2455        data = pservice->param_opt;
2456        if (data)
2457                DEBUG(5,("Freeing parametrics:\n"));
2458        while (data) {
2459                DEBUG(5,("[%s = %s]\n", data->key, data->value));
2460                string_free(&data->key);
2461                string_free(&data->value);
2462                str_list_free(&data->list);
2463                pdata = data->next;
2464                SAFE_FREE(data);
2465                data = pdata;
2466        }
2467
2468        ZERO_STRUCTP(pservice);
2469}
2470
2471
2472/***************************************************************************
2473 remove a service indexed in the ServicePtrs array from the ServiceHash
2474 and free the dynamically allocated parts
2475***************************************************************************/
2476
2477static void free_service_byindex(int idx)
2478{
2479        if ( !LP_SNUM_OK(idx) ) 
2480                return;
2481
2482        ServicePtrs[idx]->valid = False;
2483        invalid_services[num_invalid_services++] = idx;
2484
2485        /* we have to cleanup the hash record */
2486
2487        if (ServicePtrs[idx]->szService) {
2488                char *canon_name = canonicalize_servicename( ServicePtrs[idx]->szService );
2489               
2490                tdb_delete_bystring(ServiceHash, canon_name );
2491        }
2492
2493        free_service(ServicePtrs[idx]);
2494}
2495
2496/***************************************************************************
2497 Add a new service to the services array initialising it with the given
2498 service.
2499***************************************************************************/
2500
2501static int add_a_service(const service *pservice, const char *name)
2502{
2503        int i;
2504        service tservice;
2505        int num_to_alloc = iNumServices + 1;
2506        param_opt_struct *data, *pdata;
2507
2508        tservice = *pservice;
2509
2510        /* it might already exist */
2511        if (name) {
2512                i = getservicebyname(name, NULL);
2513                if (i >= 0) {
2514                        /* Clean all parametric options for service */
2515                        /* They will be added during parsing again */
2516                        data = ServicePtrs[i]->param_opt;
2517                        while (data) {
2518                                string_free(&data->key);
2519                                string_free(&data->value);
2520                                str_list_free(&data->list);
2521                                pdata = data->next;
2522                                SAFE_FREE(data);
2523                                data = pdata;
2524                        }
2525                        ServicePtrs[i]->param_opt = NULL;
2526                        return (i);
2527                }
2528        }
2529
2530        /* find an invalid one */
2531        i = iNumServices;
2532        if (num_invalid_services > 0) {
2533                i = invalid_services[--num_invalid_services];
2534        }
2535
2536        /* if not, then create one */
2537        if (i == iNumServices) {
2538                service **tsp;
2539                int *tinvalid;
2540               
2541                tsp = SMB_REALLOC_ARRAY_KEEP_OLD_ON_ERROR(ServicePtrs, service *, num_to_alloc);
2542                if (tsp == NULL) {
2543                        DEBUG(0,("add_a_service: failed to enlarge ServicePtrs!\n"));
2544                        return (-1);
2545                }
2546                ServicePtrs = tsp;
2547                ServicePtrs[iNumServices] = SMB_MALLOC_P(service);
2548                if (!ServicePtrs[iNumServices]) {
2549                        DEBUG(0,("add_a_service: out of memory!\n"));
2550                        return (-1);
2551                }
2552                iNumServices++;
2553
2554                /* enlarge invalid_services here for now... */
2555                tinvalid = SMB_REALLOC_ARRAY_KEEP_OLD_ON_ERROR(invalid_services, int,
2556                                             num_to_alloc);
2557                if (tinvalid == NULL) {
2558                        DEBUG(0,("add_a_service: failed to enlarge "
2559                                 "invalid_services!\n"));
2560                        return (-1);
2561                }
2562                invalid_services = tinvalid;
2563        } else {
2564                free_service_byindex(i);
2565        }
2566
2567        ServicePtrs[i]->valid = True;
2568
2569        init_service(ServicePtrs[i]);
2570        copy_service(ServicePtrs[i], &tservice, NULL);
2571        if (name)
2572                string_set(&ServicePtrs[i]->szService, name);
2573               
2574        DEBUG(8,("add_a_service: Creating snum = %d for %s\n", 
2575                i, ServicePtrs[i]->szService));
2576
2577        if (!hash_a_service(ServicePtrs[i]->szService, i)) {
2578                return (-1);
2579        }
2580               
2581        return (i);
2582}
2583
2584/***************************************************************************
2585  Convert a string to uppercase and remove whitespaces.
2586***************************************************************************/
2587
2588static char *canonicalize_servicename(const char *src)
2589{
2590        static fstring canon; /* is fstring large enough? */
2591
2592        if ( !src ) {
2593                DEBUG(0,("canonicalize_servicename: NULL source name!\n"));
2594                return NULL;
2595        }
2596
2597        fstrcpy( canon, src );
2598        strlower_m( canon );
2599
2600        return canon;
2601}
2602
2603/***************************************************************************
2604  Add a name/index pair for the services array to the hash table.
2605***************************************************************************/
2606
2607static BOOL hash_a_service(const char *name, int idx)
2608{
2609        char *canon_name;
2610
2611        if ( !ServiceHash ) {
2612                DEBUG(10,("hash_a_service: creating tdb servicehash\n"));
2613                ServiceHash = tdb_open("servicehash", 1031, TDB_INTERNAL, 
2614                                        (O_RDWR|O_CREAT), 0600);
2615                if ( !ServiceHash ) {
2616                        DEBUG(0,("hash_a_service: open tdb servicehash failed!\n"));
2617                        return False;
2618                }
2619        }
2620
2621        DEBUG(10,("hash_a_service: hashing index %d for service name %s\n",
2622                idx, name));
2623
2624        if ( !(canon_name = canonicalize_servicename( name )) )
2625                return False;
2626
2627        tdb_store_int32(ServiceHash, canon_name, idx);
2628
2629        return True;
2630}
2631
2632/***************************************************************************
2633 Add a new home service, with the specified home directory, defaults coming
2634 from service ifrom.
2635***************************************************************************/
2636
2637BOOL lp_add_home(const char *pszHomename, int iDefaultService, 
2638                 const char *user, const char *pszHomedir)
2639{
2640        int i;
2641        pstring newHomedir;
2642
2643        i = add_a_service(ServicePtrs[iDefaultService], pszHomename);
2644
2645        if (i < 0)
2646                return (False);
2647
2648        if (!(*(ServicePtrs[iDefaultService]->szPath))
2649            || strequal(ServicePtrs[iDefaultService]->szPath, lp_pathname(GLOBAL_SECTION_SNUM))) {
2650                pstrcpy(newHomedir, pszHomedir);
2651                string_set(&ServicePtrs[i]->szPath, newHomedir);
2652        } 
2653
2654        if (!(*(ServicePtrs[i]->comment))) {
2655                pstring comment;
2656                slprintf(comment, sizeof(comment) - 1,
2657                         "Home directory of %s", user);
2658                string_set(&ServicePtrs[i]->comment, comment);
2659        }
2660
2661        /* set the browseable flag from the global default */
2662
2663        ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
2664
2665        ServicePtrs[i]->autoloaded = True;
2666
2667        DEBUG(3, ("adding home's share [%s] for user '%s' at '%s'\n", pszHomename, 
2668               user, ServicePtrs[i]->szPath ));
2669       
2670        return (True);
2671}
2672
2673/***************************************************************************
2674 Add a new service, based on an old one.
2675***************************************************************************/
2676
2677int lp_add_service(const char *pszService, int iDefaultService)
2678{
2679        return (add_a_service(ServicePtrs[iDefaultService], pszService));
2680}
2681
2682/***************************************************************************
2683 Add the IPC service.
2684***************************************************************************/
2685
2686static BOOL lp_add_ipc(const char *ipc_name, BOOL guest_ok)
2687{
2688        pstring comment;
2689        int i = add_a_service(&sDefault, ipc_name);
2690
2691        if (i < 0)
2692                return (False);
2693
2694        slprintf(comment, sizeof(comment) - 1,
2695                 "IPC Service (%s)", Globals.szServerString);
2696
2697        string_set(&ServicePtrs[i]->szPath, tmpdir());
2698        string_set(&ServicePtrs[i]->szUsername, "");
2699        string_set(&ServicePtrs[i]->comment, comment);
2700        string_set(&ServicePtrs[i]->fstype, "IPC");
2701        ServicePtrs[i]->iMaxConnections = 0;
2702        ServicePtrs[i]->bAvailable = True;
2703        ServicePtrs[i]->bRead_only = True;
2704        ServicePtrs[i]->bGuest_only = False;
2705        ServicePtrs[i]->bGuest_ok = guest_ok;
2706        ServicePtrs[i]->bPrint_ok = False;
2707        ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
2708
2709        DEBUG(3, ("adding IPC service\n"));
2710
2711        return (True);
2712}
2713
2714/***************************************************************************
2715 Add a new printer service, with defaults coming from service iFrom.
2716***************************************************************************/
2717
2718BOOL lp_add_printer(const char *pszPrintername, int iDefaultService)
2719{
2720        const char *comment = "From Printcap";
2721        int i = add_a_service(ServicePtrs[iDefaultService], pszPrintername);
2722
2723        if (i < 0)
2724                return (False);
2725
2726        /* note that we do NOT default the availability flag to True - */
2727        /* we take it from the default service passed. This allows all */
2728        /* dynamic printers to be disabled by disabling the [printers] */
2729        /* entry (if/when the 'available' keyword is implemented!).    */
2730
2731        /* the printer name is set to the service name. */
2732        string_set(&ServicePtrs[i]->szPrintername, pszPrintername);
2733        string_set(&ServicePtrs[i]->comment, comment);
2734
2735        /* set the browseable flag from the gloabl default */
2736        ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
2737
2738        /* Printers cannot be read_only. */
2739        ServicePtrs[i]->bRead_only = False;
2740        /* No share modes on printer services. */
2741        ServicePtrs[i]->bShareModes = False;
2742        /* No oplocks on printer services. */
2743        ServicePtrs[i]->bOpLocks = False;
2744        /* Printer services must be printable. */
2745        ServicePtrs[i]->bPrint_ok = True;
2746       
2747        DEBUG(3, ("adding printer service %s\n", pszPrintername));
2748
2749        return (True);
2750}
2751
2752/***************************************************************************
2753 Map a parameter's string representation to something we can use.
2754 Returns False if the parameter string is not recognised, else TRUE.
2755***************************************************************************/
2756
2757static int map_parameter(const char *pszParmName)
2758{
2759        int iIndex;
2760
2761        if (*pszParmName == '-')
2762                return (-1);
2763
2764        for (iIndex = 0; parm_table[iIndex].label; iIndex++)
2765                if (strwicmp(parm_table[iIndex].label, pszParmName) == 0)
2766                        return (iIndex);
2767
2768        /* Warn only if it isn't parametric option */
2769        if (strchr(pszParmName, ':') == NULL)
2770                DEBUG(0, ("Unknown parameter encountered: \"%s\"\n", pszParmName));
2771        /* We do return 'fail' for parametric options as well because they are
2772           stored in different storage
2773         */
2774        return (-1);
2775}
2776
2777/***************************************************************************
2778 Show all parameter's name, type, [values,] and flags.
2779***************************************************************************/
2780
2781void show_parameter_list(void)
2782{
2783        int classIndex, parmIndex, enumIndex, flagIndex;
2784        BOOL hadFlag;
2785        const char *section_names[] = { "local", "global", NULL};
2786        const char *type[] = { "P_BOOL", "P_BOOLREV", "P_CHAR", "P_INTEGER",
2787                "P_OCTAL", "P_LIST", "P_STRING", "P_USTRING", "P_GSTRING",
2788                "P_UGSTRING", "P_ENUM", "P_SEP"};
2789        unsigned flags[] = { FLAG_BASIC, FLAG_SHARE, FLAG_PRINT, FLAG_GLOBAL,
2790                FLAG_WIZARD, FLAG_ADVANCED, FLAG_DEVELOPER, FLAG_DEPRECATED,
2791                FLAG_HIDE, FLAG_DOS_STRING};
2792        const char *flag_names[] = { "FLAG_BASIC", "FLAG_SHARE", "FLAG_PRINT",
2793                "FLAG_GLOBAL", "FLAG_WIZARD", "FLAG_ADVANCED", "FLAG_DEVELOPER",
2794                "FLAG_DEPRECATED", "FLAG_HIDE", "FLAG_DOS_STRING", NULL};
2795
2796        for ( classIndex=0; section_names[classIndex]; classIndex++) {
2797                printf("[%s]\n", section_names[classIndex]);
2798                for (parmIndex = 0; parm_table[parmIndex].label; parmIndex++) {
2799                        if (parm_table[parmIndex].p_class == classIndex) {
2800                                printf("%s=%s", 
2801                                        parm_table[parmIndex].label,
2802                                        type[parm_table[parmIndex].type]);
2803                                switch (parm_table[parmIndex].type) {
2804                                case P_ENUM:
2805                                        printf(",");
2806                                        for (enumIndex=0; parm_table[parmIndex].enum_list[enumIndex].name; enumIndex++)
2807                                                printf("%s%s",
2808                                                        enumIndex ? "|" : "",
2809                                                        parm_table[parmIndex].enum_list[enumIndex].name);
2810                                        break;
2811                                default:
2812                                        break;
2813                                }
2814                                printf(",");
2815                                hadFlag = False;
2816                                for ( flagIndex=0; flag_names[flagIndex]; flagIndex++ ) {
2817                                        if (parm_table[parmIndex].flags & flags[flagIndex]) {
2818                                                printf("%s%s",
2819                                                        hadFlag ? "|" : "",
2820                                                        flag_names[flagIndex]);
2821                                                hadFlag = True;
2822                                        }
2823                                }
2824                                printf("\n");
2825                        }
2826                }
2827        }
2828}
2829
2830/***************************************************************************
2831 Set a boolean variable from the text value stored in the passed string.
2832 Returns True in success, False if the passed string does not correctly
2833 represent a boolean.
2834***************************************************************************/
2835
2836static BOOL set_boolean(BOOL *pb, const char *pszParmValue)
2837{
2838        BOOL bRetval;
2839
2840        bRetval = True;
2841        if (strwicmp(pszParmValue, "yes") == 0 ||
2842            strwicmp(pszParmValue, "true") == 0 ||
2843            strwicmp(pszParmValue, "1") == 0)
2844                *pb = True;
2845        else if (strwicmp(pszParmValue, "no") == 0 ||
2846                    strwicmp(pszParmValue, "False") == 0 ||
2847                    strwicmp(pszParmValue, "0") == 0)
2848                *pb = False;
2849        else {
2850                DEBUG(0,
2851                      ("ERROR: Badly formed boolean in configuration file: \"%s\".\n",
2852                       pszParmValue));
2853                bRetval = False;
2854        }
2855        return (bRetval);
2856}
2857
2858/***************************************************************************
2859Find a service by name. Otherwise works like get_service.
2860***************************************************************************/
2861
2862static int getservicebyname(const char *pszServiceName, service * pserviceDest)
2863{
2864        int iService = -1;
2865        char *canon_name;
2866
2867        if (ServiceHash != NULL) {
2868                if ( !(canon_name = canonicalize_servicename( pszServiceName )) )
2869                        return -1;
2870
2871                iService = tdb_fetch_int32(ServiceHash, canon_name );
2872
2873                if (LP_SNUM_OK(iService)) {
2874                        if (pserviceDest != NULL) {
2875                                copy_service(pserviceDest, ServicePtrs[iService], NULL);
2876                        }
2877                } else {
2878                        iService = -1;
2879                }
2880        }
2881
2882        return (iService);
2883}
2884
2885/***************************************************************************
2886 Copy a service structure to another.
2887 If pcopymapDest is NULL then copy all fields
2888***************************************************************************/
2889
2890static void copy_service(service * pserviceDest, service * pserviceSource, BOOL *pcopymapDest)
2891{
2892        int i;
2893        BOOL bcopyall = (pcopymapDest == NULL);
2894        param_opt_struct *data, *pdata, *paramo;
2895        BOOL not_added;
2896
2897        for (i = 0; parm_table[i].label; i++)
2898                if (parm_table[i].ptr && parm_table[i].p_class == P_LOCAL &&
2899                    (bcopyall || pcopymapDest[i])) {
2900                        void *def_ptr = parm_table[i].ptr;
2901                        void *src_ptr =
2902                                ((char *)pserviceSource) + PTR_DIFF(def_ptr,
2903                                                                    &sDefault);
2904                        void *dest_ptr =
2905                                ((char *)pserviceDest) + PTR_DIFF(def_ptr,
2906                                                                  &sDefault);
2907
2908                        switch (parm_table[i].type) {
2909                                case P_BOOL:
2910                                case P_BOOLREV:
2911                                        *(BOOL *)dest_ptr = *(BOOL *)src_ptr;
2912                                        break;
2913
2914                                case P_INTEGER:
2915                                case P_ENUM:
2916                                case P_OCTAL:
2917                                        *(int *)dest_ptr = *(int *)src_ptr;
2918                                        break;
2919
2920                                case P_CHAR:
2921                                        *(char *)dest_ptr = *(char *)src_ptr;
2922                                        break;
2923
2924                                case P_STRING:
2925                                        string_set((char **)dest_ptr,
2926                                                   *(char **)src_ptr);
2927                                        break;
2928
2929                                case P_USTRING:
2930                                        string_set((char **)dest_ptr,
2931                                                   *(char **)src_ptr);
2932                                        strupper_m(*(char **)dest_ptr);
2933                                        break;
2934                                case P_LIST:
2935                                        str_list_free((char ***)dest_ptr);
2936                                        str_list_copy((char ***)dest_ptr, *(const char ***)src_ptr);
2937                                        break;
2938                                default:
2939                                        break;
2940                        }
2941                }
2942
2943        if (bcopyall) {
2944                init_copymap(pserviceDest);
2945                if (pserviceSource->copymap)
2946                        memcpy((void *)pserviceDest->copymap,
2947                               (void *)pserviceSource->copymap,
2948                               sizeof(BOOL) * NUMPARAMETERS);
2949        }
2950       
2951        data = pserviceSource->param_opt;
2952        while (data) {
2953                not_added = True;
2954                pdata = pserviceDest->param_opt;
2955                /* Traverse destination */
2956                while (pdata) {
2957                        /* If we already have same option, override it */
2958                        if (strcmp(pdata->key, data->key) == 0) {
2959                                string_free(&pdata->value);
2960                                str_list_free(&data->list);
2961                                pdata->value = SMB_STRDUP(data->value);
2962                                not_added = False;
2963                                break;
2964                        }
2965                        pdata = pdata->next;
2966                }
2967                if (not_added) {
2968                    paramo = SMB_XMALLOC_P(param_opt_struct);
2969                    paramo->key = SMB_STRDUP(data->key);
2970                    paramo->value = SMB_STRDUP(data->value);
2971                    paramo->list = NULL;
2972                    DLIST_ADD(pserviceDest->param_opt, paramo);
2973                }
2974                data = data->next;
2975        }
2976}
2977
2978/***************************************************************************
2979Check a service for consistency. Return False if the service is in any way
2980incomplete or faulty, else True.
2981***************************************************************************/
2982
2983static BOOL service_ok(int iService)
2984{
2985        BOOL bRetval;
2986
2987        bRetval = True;
2988        if (ServicePtrs[iService]->szService[0] == '\0') {
2989                DEBUG(0, ("The following message indicates an internal error:\n"));
2990                DEBUG(0, ("No service name in service entry.\n"));
2991                bRetval = False;
2992        }
2993
2994        /* The [printers] entry MUST be printable. I'm all for flexibility, but */
2995        /* I can't see why you'd want a non-printable printer service...        */
2996        if (strwicmp(ServicePtrs[iService]->szService, PRINTERS_NAME) == 0) {
2997                if (!ServicePtrs[iService]->bPrint_ok) {
2998                        DEBUG(0, ("WARNING: [%s] service MUST be printable!\n",
2999                               ServicePtrs[iService]->szService));
3000                        ServicePtrs[iService]->bPrint_ok = True;
3001                }
3002                /* [printers] service must also be non-browsable. */
3003                if (ServicePtrs[iService]->bBrowseable)
3004                        ServicePtrs[iService]->bBrowseable = False;
3005        }
3006
3007        if (ServicePtrs[iService]->szPath[0] == '\0' &&
3008            strwicmp(ServicePtrs[iService]->szService, HOMES_NAME) != 0 &&
3009            ServicePtrs[iService]->szMSDfsProxy[0] == '\0'
3010            ) {
3011                DEBUG(0, ("WARNING: No path in service %s - making it unavailable!\n",
3012                        ServicePtrs[iService]->szService));
3013                ServicePtrs[iService]->bAvailable = False;
3014        }
3015
3016        /* If a service is flagged unavailable, log the fact at level 0. */
3017        if (!ServicePtrs[iService]->bAvailable)
3018                DEBUG(1, ("NOTE: Service %s is flagged unavailable.\n",
3019                          ServicePtrs[iService]->szService));
3020
3021        return (bRetval);
3022}
3023
3024static struct file_lists {
3025        struct file_lists *next;
3026        char *name;
3027        char *subfname;
3028        time_t modtime;
3029} *file_lists = NULL;
3030
3031/*******************************************************************
3032 Keep a linked list of all config files so we know when one has changed
3033 it's date and needs to be reloaded.
3034********************************************************************/
3035
3036static void add_to_file_list(const char *fname, const char *subfname)
3037{
3038        struct file_lists *f = file_lists;
3039
3040        while (f) {
3041                if (f->name && !strcmp(f->name, fname))
3042                        break;
3043                f = f->next;
3044        }
3045
3046        if (!f) {
3047                f = SMB_MALLOC_P(struct file_lists);
3048                if (!f)
3049                        return;
3050                f->next = file_lists;
3051                f->name = SMB_STRDUP(fname);
3052                if (!f->name) {
3053                        SAFE_FREE(f);
3054                        return;
3055                }
3056                f->subfname = SMB_STRDUP(subfname);
3057                if (!f->subfname) {
3058                        SAFE_FREE(f);
3059                        return;
3060                }
3061                file_lists = f;
3062                f->modtime = file_modtime(subfname);
3063        } else {
3064                time_t t = file_modtime(subfname);
3065                if (t)
3066                        f->modtime = t;
3067        }
3068}
3069
3070/*******************************************************************
3071 Check if a config file has changed date.
3072********************************************************************/
3073
3074BOOL lp_file_list_changed(void)
3075{
3076        struct file_lists *f = file_lists;
3077
3078        DEBUG(6, ("lp_file_list_changed()\n"));
3079
3080        while (f) {
3081                pstring n2;
3082                time_t mod_time;
3083
3084                pstrcpy(n2, f->name);
3085                standard_sub_basic( get_current_username(),
3086                                    current_user_info.domain,
3087                                    n2, sizeof(n2) );
3088
3089                DEBUGADD(6, ("file %s -> %s  last mod_time: %s\n",
3090                             f->name, n2, ctime(&f->modtime)));
3091
3092                mod_time = file_modtime(n2);
3093
3094                if (mod_time && ((f->modtime != mod_time) || (f->subfname == NULL) || (strcmp(n2, f->subfname) != 0))) {
3095                        DEBUGADD(6,
3096                                 ("file %s modified: %s\n", n2,
3097                                  ctime(&mod_time)));
3098                        f->modtime = mod_time;
3099                        SAFE_FREE(f->subfname);
3100                        f->subfname = SMB_STRDUP(n2);
3101                        return (True);
3102                }
3103                f = f->next;
3104        }
3105        return (False);
3106}
3107
3108/***************************************************************************
3109 Run standard_sub_basic on netbios name... needed because global_myname
3110 is not accessed through any lp_ macro.
3111 Note: We must *NOT* use string_set() here as ptr points to global_myname.
3112***************************************************************************/
3113
3114static BOOL handle_netbios_name(int snum, const char *pszParmValue, char **ptr)
3115{
3116        BOOL ret;
3117        pstring netbios_name;
3118
3119        pstrcpy(netbios_name, pszParmValue);
3120
3121        standard_sub_basic(get_current_username(), current_user_info.domain,
3122                           netbios_name, sizeof(netbios_name));
3123
3124        ret = set_global_myname(netbios_name);
3125        string_set(&Globals.szNetbiosName,global_myname());
3126       
3127        DEBUG(4, ("handle_netbios_name: set global_myname to: %s\n",
3128               global_myname()));
3129
3130        return ret;
3131}
3132
3133static BOOL handle_charset(int snum, const char *pszParmValue, char **ptr)
3134{
3135        if (strcmp(*ptr, pszParmValue) != 0) {
3136                string_set(ptr, pszParmValue);
3137                init_iconv();
3138        }
3139        return True;
3140}
3141
3142
3143
3144static BOOL handle_workgroup(int snum, const char *pszParmValue, char **ptr)
3145{
3146        BOOL ret;
3147       
3148        ret = set_global_myworkgroup(pszParmValue);
3149        string_set(&Globals.szWorkgroup,lp_workgroup());
3150       
3151        return ret;
3152}
3153
3154static BOOL handle_netbios_scope(int snum, const char *pszParmValue, char **ptr)
3155{
3156        BOOL ret;
3157       
3158        ret = set_global_scope(pszParmValue);
3159        string_set(&Globals.szNetbiosScope,global_scope());
3160
3161        return ret;
3162}
3163
3164static BOOL handle_netbios_aliases(int snum, const char *pszParmValue, char **ptr)
3165{
3166        str_list_free(&Globals.szNetbiosAliases);
3167        Globals.szNetbiosAliases = str_list_make(pszParmValue, NULL);
3168        return set_netbios_aliases((const char **)Globals.szNetbiosAliases);
3169}
3170
3171/***************************************************************************
3172 Handle the include operation.
3173***************************************************************************/
3174
3175static BOOL handle_include(int snum, const char *pszParmValue, char **ptr)
3176{
3177        pstring fname;
3178        pstrcpy(fname, pszParmValue);
3179
3180        standard_sub_basic(get_current_username(), current_user_info.domain,
3181                           fname,sizeof(fname));
3182
3183        add_to_file_list(pszParmValue, fname);
3184
3185        string_set(ptr, fname);
3186
3187        if (file_exist(fname, NULL))
3188                return (pm_process(fname, do_section, do_parameter));
3189
3190        DEBUG(2, ("Can't find include file %s\n", fname));
3191
3192        return (False);
3193}
3194
3195/***************************************************************************
3196 Handle the interpretation of the copy parameter.
3197***************************************************************************/
3198
3199static BOOL handle_copy(int snum, const char *pszParmValue, char **ptr)
3200{
3201        BOOL bRetval;
3202        int iTemp;
3203        service serviceTemp;
3204
3205        string_set(ptr, pszParmValue);
3206
3207        init_service(&serviceTemp);
3208
3209        bRetval = False;
3210
3211        DEBUG(3, ("Copying service from service %s\n", pszParmValue));
3212
3213        if ((iTemp = getservicebyname(pszParmValue, &serviceTemp)) >= 0) {
3214                if (iTemp == iServiceIndex) {
3215                        DEBUG(0, ("Can't copy service %s - unable to copy self!\n", pszParmValue));
3216                } else {
3217                        copy_service(ServicePtrs[iServiceIndex],
3218                                     &serviceTemp,
3219                                     ServicePtrs[iServiceIndex]->copymap);
3220                        bRetval = True;
3221                }
3222        } else {
3223                DEBUG(0, ("Unable to copy service - source not found: %s\n", pszParmValue));
3224                bRetval = False;
3225        }
3226
3227        free_service(&serviceTemp);
3228        return (bRetval);
3229}
3230
3231/***************************************************************************
3232 Handle idmap/non unix account uid and gid allocation parameters.  The format of these
3233 parameters is:
3234
3235 [global]
3236
3237        idmap uid = 1000-1999
3238        idmap gid = 700-899
3239
3240 We only do simple parsing checks here.  The strings are parsed into useful
3241 structures in the idmap daemon code.
3242
3243***************************************************************************/
3244
3245/* Some lp_ routines to return idmap [ug]id information */
3246
3247static uid_t idmap_uid_low, idmap_uid_high;
3248static gid_t idmap_gid_low, idmap_gid_high;
3249
3250BOOL lp_idmap_uid(uid_t *low, uid_t *high)
3251{
3252        if (idmap_uid_low == 0 || idmap_uid_high == 0)
3253                return False;
3254
3255        if (low)
3256                *low = idmap_uid_low;
3257
3258        if (high)
3259                *high = idmap_uid_high;
3260
3261        return True;
3262}
3263
3264BOOL lp_idmap_gid(gid_t *low, gid_t *high)
3265{
3266        if (idmap_gid_low == 0 || idmap_gid_high == 0)
3267                return False;
3268
3269        if (low)
3270                *low = idmap_gid_low;
3271
3272        if (high)
3273                *high = idmap_gid_high;
3274
3275        return True;
3276}
3277
3278/* Do some simple checks on "idmap [ug]id" parameter values */
3279
3280static BOOL handle_idmap_uid(int snum, const char *pszParmValue, char **ptr)
3281{
3282        uint32 low, high;
3283
3284        if (sscanf(pszParmValue, "%u - %u", &low, &high) != 2 || high < low)
3285                return False;
3286
3287        /* Parse OK */
3288
3289        string_set(ptr, pszParmValue);
3290
3291        idmap_uid_low = low;
3292        idmap_uid_high = high;
3293
3294        return True;
3295}
3296
3297static BOOL handle_idmap_gid(int snum, const char *pszParmValue, char **ptr)
3298{
3299        uint32 low, high;
3300
3301        if (sscanf(pszParmValue, "%u - %u", &low, &high) != 2 || high < low)
3302                return False;
3303
3304        /* Parse OK */
3305
3306        string_set(ptr, pszParmValue);
3307
3308        idmap_gid_low = low;
3309        idmap_gid_high = high;
3310
3311        return True;
3312}
3313
3314/***************************************************************************
3315 Handle the DEBUG level list.
3316***************************************************************************/
3317
3318static BOOL handle_debug_list( int snum, const char *pszParmValueIn, char **ptr )
3319{
3320        pstring pszParmValue;
3321
3322        pstrcpy(pszParmValue, pszParmValueIn);
3323        string_set(ptr, pszParmValueIn);
3324        return debug_parse_levels( pszParmValue );
3325}
3326
3327/***************************************************************************
3328 Handle ldap suffixes - default to ldapsuffix if sub-suffixes are not defined.
3329***************************************************************************/
3330
3331static const char *append_ldap_suffix( const char *str )
3332{
3333        const char *suffix_string;
3334
3335
3336        if (!lp_talloc)
3337                lp_talloc = talloc_init("lp_talloc");
3338
3339        suffix_string = talloc_asprintf( lp_talloc, "%s,%s", str, Globals.szLdapSuffix );
3340        if ( !suffix_string ) {
3341                DEBUG(0,("append_ldap_suffix: talloc_asprintf() failed!\n"));
3342                return "";
3343        }
3344
3345        return suffix_string;
3346}
3347
3348const char *lp_ldap_machine_suffix(void)
3349{
3350        if (Globals.szLdapMachineSuffix[0])
3351                return append_ldap_suffix(Globals.szLdapMachineSuffix);
3352
3353        return lp_string(Globals.szLdapSuffix);
3354}
3355
3356const char *lp_ldap_user_suffix(void)
3357{
3358        if (Globals.szLdapUserSuffix[0])
3359                return append_ldap_suffix(Globals.szLdapUserSuffix);
3360
3361        return lp_string(Globals.szLdapSuffix);
3362}
3363
3364const char *lp_ldap_group_suffix(void)
3365{
3366        if (Globals.szLdapGroupSuffix[0])
3367                return append_ldap_suffix(Globals.szLdapGroupSuffix);
3368
3369        return lp_string(Globals.szLdapSuffix);
3370}
3371
3372const char *lp_ldap_idmap_suffix(void)
3373{
3374        if (Globals.szLdapIdmapSuffix[0])
3375                return append_ldap_suffix(Globals.szLdapIdmapSuffix);
3376
3377        return lp_string(Globals.szLdapSuffix);
3378}
3379
3380/****************************************************************************
3381 set the value for a P_ENUM
3382 ***************************************************************************/
3383
3384static void lp_set_enum_parm( struct parm_struct *parm, const char *pszParmValue,
3385                              int *ptr )
3386{
3387        int i;
3388
3389        for (i = 0; parm->enum_list[i].name; i++) {
3390                if ( strequal(pszParmValue, parm->enum_list[i].name)) {
3391                        *ptr = parm->enum_list[i].value;
3392                        break;
3393                }
3394        }
3395}
3396
3397/***************************************************************************
3398***************************************************************************/
3399
3400static BOOL handle_printing(int snum, const char *pszParmValue, char **ptr)
3401{
3402        static int parm_num = -1;
3403        service *s;
3404
3405        if ( parm_num == -1 )
3406                parm_num = map_parameter( "printing" );
3407
3408        lp_set_enum_parm( &parm_table[parm_num], pszParmValue, (int*)ptr );
3409
3410        if ( snum < 0 )
3411                s = &sDefault;
3412        else
3413                s = ServicePtrs[snum];
3414
3415        init_printer_values( s );
3416
3417        return True;
3418}
3419
3420
3421/***************************************************************************
3422 Initialise a copymap.
3423***************************************************************************/
3424
3425static void init_copymap(service * pservice)
3426{
3427        int i;
3428        SAFE_FREE(pservice->copymap);
3429        pservice->copymap = SMB_MALLOC_ARRAY(BOOL,NUMPARAMETERS);
3430        if (!pservice->copymap)
3431                DEBUG(0,
3432                      ("Couldn't allocate copymap!! (size %d)\n",
3433                       (int)NUMPARAMETERS));
3434        else
3435                for (i = 0; i < NUMPARAMETERS; i++)
3436                        pservice->copymap[i] = True;
3437}
3438
3439/***************************************************************************
3440 Return the local pointer to a parameter given the service number and the
3441 pointer into the default structure.
3442***************************************************************************/
3443
3444void *lp_local_ptr(int snum, void *ptr)
3445{
3446        return (void *)(((char *)ServicePtrs[snum]) + PTR_DIFF(ptr, &sDefault));
3447}
3448
3449/***************************************************************************
3450 Process a parameter for a particular service number. If snum < 0
3451 then assume we are in the globals.
3452***************************************************************************/
3453
3454BOOL lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue)
3455{
3456        int parmnum, i, slen;
3457        void *parm_ptr = NULL;  /* where we are going to store the result */
3458        void *def_ptr = NULL;
3459        pstring param_key;
3460        char *sep;
3461        param_opt_struct *paramo, *data;
3462        BOOL not_added;
3463
3464        parmnum = map_parameter(pszParmName);
3465
3466        if (parmnum < 0) {
3467                if ((sep=strchr(pszParmName, ':')) != NULL) {
3468                        *sep = '\0';
3469                        ZERO_STRUCT(param_key);
3470                        pstr_sprintf(param_key, "%s:", pszParmName);
3471                        slen = strlen(param_key);
3472                        pstrcat(param_key, sep+1);
3473                        trim_char(param_key+slen, ' ', ' ');
3474                        not_added = True;
3475                        data = (snum < 0) ? Globals.param_opt : 
3476                                ServicePtrs[snum]->param_opt;
3477                        /* Traverse destination */
3478                        while (data) {
3479                                /* If we already have same option, override it */
3480                                if (strcmp(data->key, param_key) == 0) {
3481                                        string_free(&data->value);
3482                                        str_list_free(&data->list);
3483                                        data->value = SMB_STRDUP(pszParmValue);
3484                                        not_added = False;
3485                                        break;
3486                                }
3487                                data = data->next;
3488                        }
3489                        if (not_added) {
3490                                paramo = SMB_XMALLOC_P(param_opt_struct);
3491                                paramo->key = SMB_STRDUP(param_key);
3492                                paramo->value = SMB_STRDUP(pszParmValue);
3493                                paramo->list = NULL;
3494                                if (snum < 0) {
3495                                        DLIST_ADD(Globals.param_opt, paramo);
3496                                } else {
3497                                        DLIST_ADD(ServicePtrs[snum]->param_opt, paramo);
3498                                }
3499                        }
3500
3501                        *sep = ':';
3502                        return (True);
3503                }
3504                DEBUG(0, ("Ignoring unknown parameter \"%s\"\n", pszParmName));
3505                return (True);
3506        }
3507
3508        if (parm_table[parmnum].flags & FLAG_DEPRECATED) {
3509                DEBUG(1, ("WARNING: The \"%s\" option is deprecated\n",
3510                          pszParmName));
3511        }
3512
3513        def_ptr = parm_table[parmnum].ptr;
3514
3515        /* we might point at a service, the default service or a global */
3516        if (snum < 0) {
3517                parm_ptr = def_ptr;
3518        } else {
3519                if (parm_table[parmnum].p_class == P_GLOBAL) {
3520                        DEBUG(0,
3521                              ("Global parameter %s found in service section!\n",
3522                               pszParmName));
3523                        return (True);
3524                }
3525                parm_ptr =
3526                        ((char *)ServicePtrs[snum]) + PTR_DIFF(def_ptr,
3527                                                            &sDefault);
3528        }
3529
3530        if (snum >= 0) {
3531                if (!ServicePtrs[snum]->copymap)
3532                        init_copymap(ServicePtrs[snum]);
3533
3534                /* this handles the aliases - set the copymap for other entries with
3535                   the same data pointer */
3536                for (i = 0; parm_table[i].label; i++)
3537                        if (parm_table[i].ptr == parm_table[parmnum].ptr)
3538                                ServicePtrs[snum]->copymap[i] = False;
3539        }
3540
3541        /* if it is a special case then go ahead */
3542        if (parm_table[parmnum].special) {
3543                parm_table[parmnum].special(snum, pszParmValue, (char **)parm_ptr);
3544                return (True);
3545        }
3546
3547        /* now switch on the type of variable it is */
3548        switch (parm_table[parmnum].type)
3549        {
3550                case P_BOOL:
3551                        *(BOOL *)parm_ptr = lp_bool(pszParmValue);
3552                        break;
3553
3554                case P_BOOLREV:
3555                        *(BOOL *)parm_ptr = !lp_bool(pszParmValue);
3556                        break;
3557
3558                case P_INTEGER:
3559                        *(int *)parm_ptr = lp_int(pszParmValue);
3560                        break;
3561
3562                case P_CHAR:
3563                        *(char *)parm_ptr = *pszParmValue;
3564                        break;
3565
3566                case P_OCTAL:
3567                        i = sscanf(pszParmValue, "%o", (int *)parm_ptr);
3568                        if ( i != 1 ) {
3569                            DEBUG ( 0, ("Invalid octal number %s\n", pszParmName ));
3570                        }
3571                        break;
3572
3573                case P_LIST:
3574                        str_list_free((char ***)parm_ptr);
3575                        *(char ***)parm_ptr = str_list_make(pszParmValue, NULL);
3576                        break;
3577
3578                case P_STRING:
3579                        string_set((char **)parm_ptr, pszParmValue);
3580                        break;
3581
3582                case P_USTRING:
3583                        string_set((char **)parm_ptr, pszParmValue);
3584                        strupper_m(*(char **)parm_ptr);
3585                        break;
3586
3587                case P_GSTRING:
3588                        pstrcpy((char *)parm_ptr, pszParmValue);
3589                        break;
3590
3591                case P_UGSTRING:
3592                        pstrcpy((char *)parm_ptr, pszParmValue);
3593                        strupper_m((char *)parm_ptr);
3594                        break;
3595
3596                case P_ENUM:
3597                        lp_set_enum_parm( &parm_table[parmnum], pszParmValue, (int*)parm_ptr );
3598                        break;
3599                case P_SEP:
3600                        break;
3601        }
3602
3603        return (True);
3604}
3605
3606/***************************************************************************
3607 Process a parameter.
3608***************************************************************************/
3609
3610static BOOL do_parameter(const char *pszParmName, const char *pszParmValue)
3611{
3612        if (!bInGlobalSection && bGlobalOnly)
3613                return (True);
3614
3615        DEBUGADD(4, ("doing parameter %s = %s\n", pszParmName, pszParmValue));
3616
3617        return (lp_do_parameter(bInGlobalSection ? -2 : iServiceIndex,
3618                                pszParmName, pszParmValue));
3619}
3620
3621/***************************************************************************
3622 Print a parameter of the specified type.
3623***************************************************************************/
3624
3625static void print_parameter(struct parm_struct *p, void *ptr, FILE * f)
3626{
3627        int i;
3628        switch (p->type)
3629        {
3630                case P_ENUM:
3631                        for (i = 0; p->enum_list[i].name; i++) {
3632                                if (*(int *)ptr == p->enum_list[i].value) {
3633                                        fprintf(f, "%s",
3634                                                p->enum_list[i].name);
3635                                        break;
3636                                }
3637                        }
3638                        break;
3639
3640                case P_BOOL:
3641                        fprintf(f, "%s", BOOLSTR(*(BOOL *)ptr));
3642                        break;
3643
3644                case P_BOOLREV:
3645                        fprintf(f, "%s", BOOLSTR(!*(BOOL *)ptr));
3646                        break;
3647
3648                case P_INTEGER:
3649                        fprintf(f, "%d", *(int *)ptr);
3650                        break;
3651
3652                case P_CHAR:
3653                        fprintf(f, "%c", *(char *)ptr);
3654                        break;
3655
3656                case P_OCTAL:
3657                        fprintf(f, "%s", octal_string(*(int *)ptr));
3658                        break;
3659
3660                case P_LIST:
3661                        if ((char ***)ptr && *(char ***)ptr) {
3662                                char **list = *(char ***)ptr;
3663                               
3664                                for (; *list; list++) {
3665                                        /* surround strings with whitespace in double quotes */
3666                                        if ( strchr_m( *list, ' ' ) )
3667                                                fprintf(f, "\"%s\"%s", *list, ((*(list+1))?", ":""));
3668                                        else
3669                                                fprintf(f, "%s%s", *list, ((*(list+1))?", ":""));
3670                                }
3671                        }
3672                        break;
3673
3674                case P_GSTRING:
3675                case P_UGSTRING:
3676                        if ((char *)ptr) {
3677                                fprintf(f, "%s", (char *)ptr);
3678                        }
3679                        break;
3680
3681                case P_STRING:
3682                case P_USTRING:
3683                        if (*(char **)ptr) {
3684                                fprintf(f, "%s", *(char **)ptr);
3685                        }
3686                        break;
3687                case P_SEP:
3688                        break;
3689        }
3690}
3691
3692/***************************************************************************
3693 Check if two parameters are equal.
3694***************************************************************************/
3695
3696static BOOL equal_parameter(parm_type type, void *ptr1, void *ptr2)
3697{
3698        switch (type) {
3699                case P_BOOL:
3700                case P_BOOLREV:
3701                        return (*((BOOL *)ptr1) == *((BOOL *)ptr2));
3702
3703                case P_INTEGER:
3704                case P_ENUM:
3705                case P_OCTAL:
3706                        return (*((int *)ptr1) == *((int *)ptr2));
3707
3708                case P_CHAR:
3709                        return (*((char *)ptr1) == *((char *)ptr2));
3710               
3711                case P_LIST:
3712                        return str_list_compare(*(char ***)ptr1, *(char ***)ptr2);
3713
3714                case P_GSTRING:
3715                case P_UGSTRING:
3716                {
3717                        char *p1 = (char *)ptr1, *p2 = (char *)ptr2;
3718                        if (p1 && !*p1)
3719                                p1 = NULL;
3720                        if (p2 && !*p2)
3721                                p2 = NULL;
3722                        return (p1 == p2 || strequal(p1, p2));
3723                }
3724                case P_STRING:
3725                case P_USTRING:
3726                {
3727                        char *p1 = *(char **)ptr1, *p2 = *(char **)ptr2;
3728                        if (p1 && !*p1)
3729                                p1 = NULL;
3730                        if (p2 && !*p2)
3731                                p2 = NULL;
3732                        return (p1 == p2 || strequal(p1, p2));
3733                }
3734                case P_SEP:
3735                        break;
3736        }
3737        return (False);
3738}
3739
3740/***************************************************************************
3741 Initialize any local varients in the sDefault table.
3742***************************************************************************/
3743
3744void init_locals(void)
3745{
3746        /* None as yet. */
3747}
3748
3749/***************************************************************************
3750 Process a new section (service). At this stage all sections are services.
3751 Later we'll have special sections that permit server parameters to be set.
3752 Returns True on success, False on failure.
3753***************************************************************************/
3754
3755static BOOL do_section(const char *pszSectionName)
3756{
3757        BOOL bRetval;
3758        BOOL isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
3759                         (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
3760        bRetval = False;
3761
3762        /* if we were in a global section then do the local inits */
3763        if (bInGlobalSection && !isglobal)
3764                init_locals();
3765
3766        /* if we've just struck a global section, note the fact. */
3767        bInGlobalSection = isglobal;
3768
3769        /* check for multiple global sections */
3770        if (bInGlobalSection) {
3771                DEBUG(3, ("Processing section \"[%s]\"\n", pszSectionName));
3772                return (True);
3773        }
3774
3775        if (!bInGlobalSection && bGlobalOnly)
3776                return (True);
3777
3778        /* if we have a current service, tidy it up before moving on */
3779        bRetval = True;
3780
3781        if (iServiceIndex >= 0)
3782                bRetval = service_ok(iServiceIndex);
3783
3784        /* if all is still well, move to the next record in the services array */
3785        if (bRetval) {
3786                /* We put this here to avoid an odd message order if messages are */
3787                /* issued by the post-processing of a previous section. */
3788                DEBUG(2, ("Processing section \"[%s]\"\n", pszSectionName));
3789
3790                if ((iServiceIndex = add_a_service(&sDefault, pszSectionName))
3791                    < 0) {
3792                        DEBUG(0, ("Failed to add a new service\n"));
3793                        return (False);
3794                }
3795        }
3796
3797        return (bRetval);
3798}
3799
3800
3801/***************************************************************************
3802 Determine if a partcular base parameter is currentl set to the default value.
3803***************************************************************************/
3804
3805static BOOL is_default(int i)
3806{
3807        if (!defaults_saved)
3808                return False;
3809        switch (parm_table[i].type) {
3810                case P_LIST:
3811                        return str_list_compare (parm_table[i].def.lvalue, 
3812                                                *(char ***)parm_table[i].ptr);
3813                case P_STRING:
3814                case P_USTRING:
3815                        return strequal(parm_table[i].def.svalue,
3816                                        *(char **)parm_table[i].ptr);
3817                case P_GSTRING:
3818                case P_UGSTRING:
3819                        return strequal(parm_table[i].def.svalue,
3820                                        (char *)parm_table[i].ptr);
3821                case P_BOOL:
3822                case P_BOOLREV:
3823                        return parm_table[i].def.bvalue ==
3824                                *(BOOL *)parm_table[i].ptr;
3825                case P_CHAR:
3826                        return parm_table[i].def.cvalue ==
3827                                *(char *)parm_table[i].ptr;
3828                case P_INTEGER:
3829                case P_OCTAL:
3830                case P_ENUM:
3831                        return parm_table[i].def.ivalue ==
3832                                *(int *)parm_table[i].ptr;
3833                case P_SEP:
3834                        break;
3835        }
3836        return False;
3837}
3838
3839/***************************************************************************
3840Display the contents of the global structure.
3841***************************************************************************/
3842
3843static void dump_globals(FILE *f)
3844{
3845        int i;
3846        param_opt_struct *data;
3847       
3848        fprintf(f, "[global]\n");
3849
3850        for (i = 0; parm_table[i].label; i++)
3851                if (parm_table[i].p_class == P_GLOBAL &&
3852                    parm_table[i].ptr &&
3853                    (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) {
3854                        if (defaults_saved && is_default(i))
3855                                continue;
3856                        fprintf(f, "\t%s = ", parm_table[i].label);
3857                        print_parameter(&parm_table[i], parm_table[i].ptr, f);
3858                        fprintf(f, "\n");
3859        }
3860        if (Globals.param_opt != NULL) {
3861                data = Globals.param_opt;
3862                while(data) {
3863                        fprintf(f, "\t%s = %s\n", data->key, data->value);
3864                        data = data->next;
3865                }
3866        }
3867
3868}
3869
3870/***************************************************************************
3871 Return True if a local parameter is currently set to the global default.
3872***************************************************************************/
3873
3874BOOL lp_is_default(int snum, struct parm_struct *parm)
3875{
3876        int pdiff = PTR_DIFF(parm->ptr, &sDefault);
3877
3878        return equal_parameter(parm->type,
3879                               ((char *)ServicePtrs[snum]) + pdiff,
3880                               ((char *)&sDefault) + pdiff);
3881}
3882
3883/***************************************************************************
3884 Display the contents of a single services record.
3885***************************************************************************/
3886
3887static void dump_a_service(service * pService, FILE * f)
3888{
3889        int i;
3890        param_opt_struct *data;
3891       
3892        if (pService != &sDefault)
3893                fprintf(f, "[%s]\n", pService->szService);
3894
3895        for (i = 0; parm_table[i].label; i++) {
3896
3897                if (parm_table[i].p_class == P_LOCAL &&
3898                    parm_table[i].ptr &&
3899                    (*parm_table[i].label != '-') &&
3900                    (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) 
3901                {
3902               
3903                        int pdiff = PTR_DIFF(parm_table[i].ptr, &sDefault);
3904
3905                        if (pService == &sDefault) {
3906                                if (defaults_saved && is_default(i))
3907                                        continue;
3908                        } else {
3909                                if (equal_parameter(parm_table[i].type,
3910                                                    ((char *)pService) +
3911                                                    pdiff,
3912                                                    ((char *)&sDefault) +
3913                                                    pdiff))
3914                                        continue;
3915                        }
3916
3917                        fprintf(f, "\t%s = ", parm_table[i].label);
3918                        print_parameter(&parm_table[i],
3919                                        ((char *)pService) + pdiff, f);
3920                        fprintf(f, "\n");
3921                }
3922        }
3923
3924                if (pService->param_opt != NULL) {
3925                        data = pService->param_opt;
3926                        while(data) {
3927                                fprintf(f, "\t%s = %s\n", data->key, data->value);
3928                                data = data->next;
3929                        }
3930                }
3931}
3932
3933/***************************************************************************
3934 Display the contents of a parameter of a single services record.
3935***************************************************************************/
3936
3937BOOL dump_a_parameter(int snum, char *parm_name, FILE * f, BOOL isGlobal)
3938{
3939        int i;
3940        BOOL result = False;
3941        parm_class p_class;
3942        unsigned flag = 0;
3943        fstring local_parm_name;
3944        char *parm_opt;
3945        const char *parm_opt_value;
3946
3947        /* check for parametrical option */
3948        fstrcpy( local_parm_name, parm_name);
3949        parm_opt = strchr( local_parm_name, ':');
3950
3951        if (parm_opt) {
3952                *parm_opt = '\0';
3953                parm_opt++;
3954                if (strlen(parm_opt)) {
3955                        parm_opt_value = lp_parm_const_string( snum,
3956                                local_parm_name, parm_opt, NULL);
3957                        if (parm_opt_value) {
3958                                printf( "%s\n", parm_opt_value);
3959                                result = True;
3960                        }
3961                }
3962                return result;
3963        }
3964
3965        /* check for a key and print the value */
3966        if (isGlobal) {
3967                p_class = P_GLOBAL;
3968                flag = FLAG_GLOBAL;
3969        } else
3970                p_class = P_LOCAL;
3971
3972        for (i = 0; parm_table[i].label; i++) {
3973                if (strwicmp(parm_table[i].label, parm_name) == 0 &&
3974                    (parm_table[i].p_class == p_class || parm_table[i].flags & flag) &&
3975                    parm_table[i].ptr &&
3976                    (*parm_table[i].label != '-') &&
3977                    (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) 
3978                {
3979                        void *ptr;
3980
3981                        if (isGlobal) {
3982                                ptr = parm_table[i].ptr;
3983                        } else {
3984                                service * pService = ServicePtrs[snum];
3985                                ptr = ((char *)pService) +
3986                                        PTR_DIFF(parm_table[i].ptr, &sDefault);
3987                        }
3988
3989                        print_parameter(&parm_table[i],
3990                                        ptr, f);
3991                        fprintf(f, "\n");
3992                        result = True;
3993                        break;
3994                }
3995        }
3996
3997        return result;
3998}
3999
4000/***************************************************************************
4001 Return info about the next service  in a service. snum==GLOBAL_SECTION_SNUM gives the globals.
4002 Return NULL when out of parameters.
4003***************************************************************************/
4004
4005struct parm_struct *lp_next_parameter(int snum, int *i, int allparameters)
4006{
4007        if (snum < 0) {
4008                /* do the globals */
4009                for (; parm_table[*i].label; (*i)++) {
4010                        if (parm_table[*i].p_class == P_SEPARATOR)
4011                                return &parm_table[(*i)++];
4012
4013                        if (!parm_table[*i].ptr
4014                            || (*parm_table[*i].label == '-'))
4015                                continue;
4016
4017                        if ((*i) > 0
4018                            && (parm_table[*i].ptr ==
4019                                parm_table[(*i) - 1].ptr))
4020                                continue;
4021
4022                        return &parm_table[(*i)++];
4023                }
4024        } else {
4025                service *pService = ServicePtrs[snum];
4026
4027                for (; parm_table[*i].label; (*i)++) {
4028                        if (parm_table[*i].p_class == P_SEPARATOR)
4029                                return &parm_table[(*i)++];
4030
4031                        if (parm_table[*i].p_class == P_LOCAL &&
4032                            parm_table[*i].ptr &&
4033                            (*parm_table[*i].label != '-') &&
4034                            ((*i) == 0 ||
4035                             (parm_table[*i].ptr !=
4036                              parm_table[(*i) - 1].ptr)))
4037                        {
4038                                int pdiff =
4039                                        PTR_DIFF(parm_table[*i].ptr,
4040                                                 &sDefault);
4041
4042                                if (allparameters ||
4043                                    !equal_parameter(parm_table[*i].type,
4044                                                     ((char *)pService) +
4045                                                     pdiff,
4046                                                     ((char *)&sDefault) +
4047                                                     pdiff))
4048                                {
4049                                        return &parm_table[(*i)++];
4050                                }
4051                        }
4052                }
4053        }
4054
4055        return NULL;
4056}
4057
4058
4059#if 0
4060/***************************************************************************
4061 Display the contents of a single copy structure.
4062***************************************************************************/
4063static void dump_copy_map(BOOL *pcopymap)
4064{
4065        int i;
4066        if (!pcopymap)
4067                return;
4068
4069        printf("\n\tNon-Copied parameters:\n");
4070
4071        for (i = 0; parm_table[i].label; i++)
4072                if (parm_table[i].p_class == P_LOCAL &&
4073                    parm_table[i].ptr && !pcopymap[i] &&
4074                    (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr)))
4075                {
4076                        printf("\t\t%s\n", parm_table[i].label);
4077                }
4078}
4079#endif
4080
4081/***************************************************************************
4082 Return TRUE if the passed service number is within range.
4083***************************************************************************/
4084
4085BOOL lp_snum_ok(int iService)
4086{
4087        return (LP_SNUM_OK(iService) && ServicePtrs[iService]->bAvailable);
4088}
4089
4090/***************************************************************************
4091 Auto-load some home services.
4092***************************************************************************/
4093
4094static void lp_add_auto_services(char *str)
4095{
4096        char *s;
4097        char *p;
4098        int homes;
4099
4100        if (!str)
4101                return;
4102
4103        s = SMB_STRDUP(str);
4104        if (!s)
4105                return;
4106
4107        homes = lp_servicenumber(HOMES_NAME);
4108
4109        for (p = strtok(s, LIST_SEP); p; p = strtok(NULL, LIST_SEP)) {
4110                char *home = get_user_home_dir(p);
4111
4112                if (lp_servicenumber(p) >= 0)
4113                        continue;
4114
4115                if (home && homes >= 0)
4116                        lp_add_home(p, homes, p, home);
4117        }
4118        SAFE_FREE(s);
4119}
4120
4121/***************************************************************************
4122 Auto-load one printer.
4123***************************************************************************/
4124
4125void lp_add_one_printer(char *name, char *comment)
4126{
4127        int printers = lp_servicenumber(PRINTERS_NAME);
4128        int i;
4129
4130        if (lp_servicenumber(name) < 0) {
4131                lp_add_printer(name, printers);
4132                if ((i = lp_servicenumber(name)) >= 0) {
4133                        string_set(&ServicePtrs[i]->comment, comment);
4134                        ServicePtrs[i]->autoloaded = True;
4135                }
4136        }
4137}
4138
4139/***************************************************************************
4140 Have we loaded a services file yet?
4141***************************************************************************/
4142
4143BOOL lp_loaded(void)
4144{
4145        return (bLoaded);
4146}
4147
4148/***************************************************************************
4149 Unload unused services.
4150***************************************************************************/
4151
4152void lp_killunused(BOOL (*snumused) (int))
4153{
4154        int i;
4155        for (i = 0; i < iNumServices; i++) {
4156                if (!VALID(i))
4157                        continue;
4158
4159                /* don't kill autoloaded or usershare services */
4160                if ( ServicePtrs[i]->autoloaded ||
4161                                ServicePtrs[i]->usershare == USERSHARE_VALID) {
4162                        continue;
4163                }
4164
4165                if (!snumused || !snumused(i)) {
4166                        free_service_byindex(i);
4167                }
4168        }
4169}
4170
4171/***************************************************************************
4172 Unload a service.
4173***************************************************************************/
4174
4175void lp_killservice(int iServiceIn)
4176{
4177        if (VALID(iServiceIn)) {
4178                free_service_byindex(iServiceIn);
4179        }
4180}
4181
4182/***************************************************************************
4183 Save the curent values of all global and sDefault parameters into the
4184 defaults union. This allows swat and testparm to show only the
4185 changed (ie. non-default) parameters.
4186***************************************************************************/
4187
4188static void lp_save_defaults(void)
4189{
4190        int i;
4191        for (i = 0; parm_table[i].label; i++) {
4192                if (i > 0 && parm_table[i].ptr == parm_table[i - 1].ptr)
4193                        continue;
4194                switch (parm_table[i].type) {
4195                        case P_LIST:
4196                                str_list_copy(&(parm_table[i].def.lvalue),
4197                                            *(const char ***)parm_table[i].ptr);
4198                                break;
4199                        case P_STRING:
4200                        case P_USTRING:
4201                                if (parm_table[i].ptr) {
4202                                        parm_table[i].def.svalue = SMB_STRDUP(*(char **)parm_table[i].ptr);
4203                                } else {
4204                                        parm_table[i].def.svalue = NULL;
4205                                }
4206                                break;
4207                        case P_GSTRING:
4208                        case P_UGSTRING:
4209                                if (parm_table[i].ptr) {
4210                                        parm_table[i].def.svalue = SMB_STRDUP((char *)parm_table[i].ptr);
4211                                } else {
4212                                        parm_table[i].def.svalue = NULL;
4213                                }
4214                                break;
4215                        case P_BOOL:
4216                        case P_BOOLREV:
4217                                parm_table[i].def.bvalue =
4218                                        *(BOOL *)parm_table[i].ptr;
4219                                break;
4220                        case P_CHAR:
4221                                parm_table[i].def.cvalue =
4222                                        *(char *)parm_table[i].ptr;
4223                                break;
4224                        case P_INTEGER:
4225                        case P_OCTAL:
4226                        case P_ENUM:
4227                                parm_table[i].def.ivalue =
4228                                        *(int *)parm_table[i].ptr;
4229                                break;
4230                        case P_SEP:
4231                                break;
4232                }
4233        }
4234        defaults_saved = True;
4235}
4236
4237/*******************************************************************
4238 Set the server type we will announce as via nmbd.
4239********************************************************************/
4240
4241static const struct srv_role_tab {
4242        uint32 role;
4243        const char *role_str;
4244} srv_role_tab [] = {
4245        { ROLE_STANDALONE, "ROLE_STANDALONE" },
4246        { ROLE_DOMAIN_MEMBER, "ROLE_DOMAIN_MEMBER" },
4247        { ROLE_DOMAIN_BDC, "ROLE_DOMAIN_BDC" },
4248        { ROLE_DOMAIN_PDC, "ROLE_DOMAIN_PDC" },
4249        { 0, NULL }
4250};
4251
4252const char* server_role_str(uint32 role)
4253{
4254        int i = 0;
4255        for (i=0; srv_role_tab[i].role_str; i++) {
4256                if (role == srv_role_tab[i].role) {
4257                        return srv_role_tab[i].role_str;
4258                }
4259        }
4260        return NULL;
4261}
4262
4263static void set_server_role(void)
4264{
4265        server_role = ROLE_STANDALONE;
4266
4267        switch (lp_security()) {
4268                case SEC_SHARE:
4269                        if (lp_domain_logons())
4270                                DEBUG(0, ("Server's Role (logon server) conflicts with share-level security\n"));
4271                        break;
4272                case SEC_SERVER:
4273                        if (lp_domain_logons())
4274                                DEBUG(0, ("Server's Role (logon server) conflicts with server-level security\n"));
4275                        /* this used to be considered ROLE_DOMAIN_MEMBER but that's just wrong */
4276                        server_role = ROLE_STANDALONE;
4277                        break;
4278                case SEC_DOMAIN:
4279                        if (lp_domain_logons()) {
4280                                DEBUG(1, ("Server's Role (logon server) NOT ADVISED with domain-level security\n"));
4281                                server_role = ROLE_DOMAIN_BDC;
4282                                break;
4283                        }
4284                        server_role = ROLE_DOMAIN_MEMBER;
4285                        break;
4286                case SEC_ADS:
4287                        if (lp_domain_logons()) {
4288                                server_role = ROLE_DOMAIN_PDC;
4289                                break;
4290                        }
4291                        server_role = ROLE_DOMAIN_MEMBER;
4292                        break;
4293                case SEC_USER:
4294                        if (lp_domain_logons()) {
4295
4296                                if (Globals.bDomainMaster) /* auto or yes */ 
4297                                        server_role = ROLE_DOMAIN_PDC;
4298                                else
4299                                        server_role = ROLE_DOMAIN_BDC;
4300                        }
4301                        break;
4302                default:
4303                        DEBUG(0, ("Server's Role undefined due to unknown security mode\n"));
4304                        break;
4305        }
4306
4307        DEBUG(10, ("set_server_role: role = %s\n", server_role_str(server_role)));
4308}
4309
4310/***********************************************************
4311 If we should send plaintext/LANMAN passwords in the clinet
4312************************************************************/
4313
4314static void set_allowed_client_auth(void)
4315{
4316        if (Globals.bClientNTLMv2Auth) {
4317                Globals.bClientLanManAuth = False;
4318        }
4319        if (!Globals.bClientLanManAuth) {
4320                Globals.bClientPlaintextAuth = False;
4321        }
4322}
4323
4324/***************************************************************************
4325 JRA.
4326 The following code allows smbd to read a user defined share file.
4327 Yes, this is my intent. Yes, I'm comfortable with that...
4328
4329 THE FOLLOWING IS SECURITY CRITICAL CODE.
4330
4331 It washes your clothes, it cleans your house, it guards you while you sleep...
4332 Do not f%^k with it....
4333***************************************************************************/
4334
4335#define MAX_USERSHARE_FILE_SIZE (10*1024)
4336
4337/***************************************************************************
4338 Check allowed stat state of a usershare file.
4339 Ensure we print out who is dicking with us so the admin can
4340 get their sorry ass fired.
4341***************************************************************************/
4342
4343static BOOL check_usershare_stat(const char *fname, SMB_STRUCT_STAT *psbuf)
4344{
4345        if (!S_ISREG(psbuf->st_mode)) {
4346                DEBUG(0,("check_usershare_stat: file %s owned by uid %u is "
4347                        "not a regular file\n",
4348                        fname, (unsigned int)psbuf->st_uid ));
4349                return False;
4350        }
4351
4352        /* Ensure this doesn't have the other write bit set. */
4353        if (psbuf->st_mode & S_IWOTH) {
4354                DEBUG(0,("check_usershare_stat: file %s owned by uid %u allows "
4355                        "public write. Refusing to allow as a usershare file.\n",
4356                        fname, (unsigned int)psbuf->st_uid ));
4357                return False;
4358        }
4359
4360        /* Should be 10k or less. */
4361        if (psbuf->st_size > MAX_USERSHARE_FILE_SIZE) {
4362                DEBUG(0,("check_usershare_stat: file %s owned by uid %u is "
4363                        "too large (%u) to be a user share file.\n",
4364                        fname, (unsigned int)psbuf->st_uid,
4365                        (unsigned int)psbuf->st_size ));
4366                return False;
4367        }
4368
4369        return True;
4370}
4371
4372/***************************************************************************
4373 Parse the contents of a usershare file.
4374***************************************************************************/
4375
4376enum usershare_err parse_usershare_file(TALLOC_CTX *ctx, 
4377                        SMB_STRUCT_STAT *psbuf,
4378                        const char *servicename,
4379                        int snum,
4380                        char **lines,
4381                        int numlines,
4382                        pstring sharepath,
4383                        pstring comment,
4384                        SEC_DESC **ppsd,
4385                        BOOL *pallow_guest)
4386{
4387        const char **prefixallowlist = lp_usershare_prefix_allow_list();
4388        const char **prefixdenylist = lp_usershare_prefix_deny_list();
4389        int us_vers;
4390        SMB_STRUCT_DIR *dp;
4391        SMB_STRUCT_STAT sbuf;
4392
4393        *pallow_guest = False;
4394
4395        if (numlines < 4) {
4396                return USERSHARE_MALFORMED_FILE;
4397        }
4398
4399        if (strcmp(lines[0], "#VERSION 1") == 0) {
4400                us_vers = 1;
4401        } else if (strcmp(lines[0], "#VERSION 2") == 0) {
4402                us_vers = 2;
4403                if (numlines < 5) {
4404                        return USERSHARE_MALFORMED_FILE;
4405                }
4406        } else {
4407                return USERSHARE_BAD_VERSION;
4408        }
4409
4410        if (strncmp(lines[1], "path=", 5) != 0) {
4411                return USERSHARE_MALFORMED_PATH;
4412        }
4413
4414        pstrcpy(sharepath, &lines[1][5]);
4415        trim_string(sharepath, " ", " ");
4416
4417        if (strncmp(lines[2], "comment=", 8) != 0) {
4418                return USERSHARE_MALFORMED_COMMENT_DEF;
4419        }
4420
4421        pstrcpy(comment, &lines[2][8]);
4422        trim_string(comment, " ", " ");
4423        trim_char(comment, '"', '"');
4424
4425        if (strncmp(lines[3], "usershare_acl=", 14) != 0) {
4426                return USERSHARE_MALFORMED_ACL_DEF;
4427        }
4428
4429        if (!parse_usershare_acl(ctx, &lines[3][14], ppsd)) {
4430                return USERSHARE_ACL_ERR;
4431        }
4432
4433        if (us_vers == 2) {
4434                if (strncmp(lines[4], "guest_ok=", 9) != 0) {
4435                        return USERSHARE_MALFORMED_ACL_DEF;
4436                }
4437                if (lines[4][9] == 'y') {
4438                        *pallow_guest = True;
4439                }
4440        }
4441
4442        if (snum != -1 && (strcmp(sharepath, ServicePtrs[snum]->szPath) == 0)) {
4443                /* Path didn't change, no checks needed. */
4444                return USERSHARE_OK;
4445        }
4446
4447        /* The path *must* be absolute. */
4448        if (sharepath[0] != '/') {
4449                DEBUG(2,("parse_usershare_file: share %s: path %s is not an absolute path.\n",
4450                        servicename, sharepath));
4451                return USERSHARE_PATH_NOT_ABSOLUTE;
4452        }
4453
4454        /* If there is a usershare prefix deny list ensure one of these paths
4455           doesn't match the start of the user given path. */
4456        if (prefixdenylist) {
4457                int i;
4458                for ( i=0; prefixdenylist[i]; i++ ) {
4459                        DEBUG(10,("parse_usershare_file: share %s : checking prefixdenylist[%d]='%s' against %s\n",
4460                                servicename, i, prefixdenylist[i], sharepath ));
4461                        if (memcmp( sharepath, prefixdenylist[i], strlen(prefixdenylist[i])) == 0) {
4462                                DEBUG(2,("parse_usershare_file: share %s path %s starts with one of the "
4463                                        "usershare prefix deny list entries.\n",
4464                                        servicename, sharepath));
4465                                return USERSHARE_PATH_IS_DENIED;
4466                        }
4467                }
4468        }
4469
4470        /* If there is a usershare prefix allow list ensure one of these paths
4471           does match the start of the user given path. */
4472
4473        if (prefixallowlist) {
4474                int i;
4475                for ( i=0; prefixallowlist[i]; i++ ) {
4476                        DEBUG(10,("parse_usershare_file: share %s checking prefixallowlist[%d]='%s' against %s\n",
4477                                servicename, i, prefixallowlist[i], sharepath ));
4478                        if (memcmp( sharepath, prefixallowlist[i], strlen(prefixallowlist[i])) == 0) {
4479                                break;
4480                        }
4481                }
4482                if (prefixallowlist[i] == NULL) {
4483                        DEBUG(2,("parse_usershare_file: share %s path %s doesn't start with one of the "
4484                                "usershare prefix allow list entries.\n",
4485                                servicename, sharepath));
4486                        return USERSHARE_PATH_NOT_ALLOWED;
4487                }
4488        }
4489
4490        /* Ensure this is pointing to a directory. */
4491        dp = sys_opendir(sharepath);
4492
4493        if (!dp) {
4494                DEBUG(2,("parse_usershare_file: share %s path %s is not a directory.\n",
4495                        servicename, sharepath));
4496                return USERSHARE_PATH_NOT_DIRECTORY;
4497        }
4498
4499        /* Ensure the owner of the usershare file has permission to share
4500           this directory. */
4501
4502        if (sys_stat(sharepath, &sbuf) == -1) {
4503                DEBUG(2,("parse_usershare_file: share %s : stat failed on path %s. %s\n",
4504                        servicename, sharepath, strerror(errno) ));
4505                sys_closedir(dp);
4506                return USERSHARE_POSIX_ERR;
4507        }
4508
4509        sys_closedir(dp);
4510
4511        if (!S_ISDIR(sbuf.st_mode)) {
4512                DEBUG(2,("parse_usershare_file: share %s path %s is not a directory.\n",
4513                        servicename, sharepath ));
4514                return USERSHARE_PATH_NOT_DIRECTORY;
4515        }
4516
4517        /* Check if sharing is restricted to owner-only. */
4518        /* psbuf is the stat of the usershare definition file,
4519           sbuf is the stat of the target directory to be shared. */
4520
4521        if (lp_usershare_owner_only()) {
4522                /* root can share anything. */
4523                if ((psbuf->st_uid != 0) && (sbuf.st_uid != psbuf->st_uid)) {
4524                        return USERSHARE_PATH_NOT_ALLOWED;
4525                }
4526        }
4527
4528        return USERSHARE_OK;
4529}
4530
4531/***************************************************************************
4532 Deal with a usershare file.
4533 Returns:
4534        >= 0 - snum
4535        -1 - Bad name, invalid contents.
4536           - service name already existed and not a usershare, problem
4537            with permissions to share directory etc.
4538***************************************************************************/
4539
4540static int process_usershare_file(const char *dir_name, const char *file_name, int snum_template)
4541{
4542        SMB_STRUCT_STAT sbuf;
4543        SMB_STRUCT_STAT lsbuf;
4544        pstring fname;
4545        pstring sharepath;
4546        pstring comment;
4547        fstring service_name;
4548        char **lines = NULL;
4549        int numlines = 0;
4550        int fd = -1;
4551        int iService = -1;
4552        TALLOC_CTX *ctx = NULL;
4553        SEC_DESC *psd = NULL;
4554        BOOL guest_ok = False;
4555
4556        /* Ensure share name doesn't contain invalid characters. */
4557        if (!validate_net_name(file_name, INVALID_SHARENAME_CHARS, strlen(file_name))) {
4558                DEBUG(0,("process_usershare_file: share name %s contains "
4559                        "invalid characters (any of %s)\n",
4560                        file_name, INVALID_SHARENAME_CHARS ));
4561                return -1;
4562        }
4563
4564        fstrcpy(service_name, file_name);
4565
4566        pstrcpy(fname, dir_name);
4567        pstrcat(fname, "/");
4568        pstrcat(fname, file_name);
4569
4570        /* Minimize the race condition by doing an lstat before we
4571           open and fstat. Ensure this isn't a symlink link. */
4572
4573        if (sys_lstat(fname, &lsbuf) != 0) {
4574                DEBUG(0,("process_usershare_file: stat of %s failed. %s\n",
4575                        fname, strerror(errno) ));
4576                return -1;
4577        }
4578
4579        /* This must be a regular file, not a symlink, directory or
4580           other strange filetype. */
4581        if (!check_usershare_stat(fname, &lsbuf)) {
4582                return -1;
4583        }
4584
4585        /* See if there is already a servicenum for this name. */
4586        /* tdb_fetch_int32 returns -1 if not found. */
4587        iService = (int)tdb_fetch_int32(ServiceHash, canonicalize_servicename(service_name) );
4588
4589        if (iService != -1 && ServicePtrs[iService]->usershare_last_mod == lsbuf.st_mtime) {
4590                /* Nothing changed - Mark valid and return. */
4591                DEBUG(10,("process_usershare_file: service %s not changed.\n",
4592                        service_name ));
4593                ServicePtrs[iService]->usershare = USERSHARE_VALID;
4594                return iService;
4595        }
4596
4597        /* Try and open the file read only - no symlinks allowed. */
4598#ifdef O_NOFOLLOW
4599        fd = sys_open(fname, O_RDONLY|O_NOFOLLOW, 0);
4600#else
4601        fd = sys_open(fname, O_RDONLY, 0);
4602#endif
4603
4604        if (fd == -1) {
4605                DEBUG(0,("process_usershare_file: unable to open %s. %s\n",
4606                        fname, strerror(errno) ));
4607                return -1;
4608        }
4609
4610        /* Now fstat to be *SURE* it's a regular file. */
4611        if (sys_fstat(fd, &sbuf) != 0) {
4612                close(fd);
4613                DEBUG(0,("process_usershare_file: fstat of %s failed. %s\n",
4614                        fname, strerror(errno) ));
4615                return -1;
4616        }
4617
4618        /* Is it the same dev/inode as was lstated ? */
4619        if (lsbuf.st_dev != sbuf.st_dev || lsbuf.st_ino != sbuf.st_ino) {
4620                close(fd);
4621                DEBUG(0,("process_usershare_file: fstat of %s is a different file from lstat. "
4622                        "Symlink spoofing going on ?\n", fname ));
4623                return -1;
4624        }
4625
4626        /* This must be a regular file, not a symlink, directory or
4627           other strange filetype. */
4628        if (!check_usershare_stat(fname, &sbuf)) {
4629                return -1;
4630        }
4631
4632        lines = fd_lines_load(fd, &numlines, MAX_USERSHARE_FILE_SIZE);
4633
4634        close(fd);
4635        if (lines == NULL) {
4636                DEBUG(0,("process_usershare_file: loading file %s owned by %u failed.\n",
4637                        fname, (unsigned int)sbuf.st_uid ));
4638                return -1;
4639        }
4640
4641        /* Should we allow printers to be shared... ? */
4642        ctx = talloc_init("usershare_sd_xctx");
4643        if (!ctx) {
4644                file_lines_free(lines);
4645                return 1;
4646        }
4647
4648        if (parse_usershare_file(ctx, &sbuf, service_name,
4649                        iService, lines, numlines, sharepath,
4650                        comment, &psd, &guest_ok) != USERSHARE_OK) {
4651                talloc_destroy(ctx);
4652                file_lines_free(lines);
4653                return -1;
4654        }
4655
4656        file_lines_free(lines);
4657
4658        /* Everything ok - add the service possibly using a template. */
4659        if (iService < 0) {
4660                const service *sp = &sDefault;
4661                if (snum_template != -1) {
4662                        sp = ServicePtrs[snum_template];
4663                }
4664
4665                if ((iService = add_a_service(sp, service_name)) < 0) {
4666                        DEBUG(0, ("process_usershare_file: Failed to add "
4667                                "new service %s\n", service_name));
4668                        talloc_destroy(ctx);
4669                        return -1;
4670                }
4671
4672                /* Read only is controlled by usershare ACL below. */
4673                ServicePtrs[iService]->bRead_only = False;
4674        }
4675
4676        /* Write the ACL of the new/modified share. */
4677        if (!set_share_security(service_name, psd)) {
4678                 DEBUG(0, ("process_usershare_file: Failed to set share "
4679                        "security for user share %s\n",
4680                        service_name ));
4681                lp_remove_service(iService);
4682                talloc_destroy(ctx);
4683                return -1;
4684        }
4685
4686        talloc_destroy(ctx);
4687
4688        /* If from a template it may be marked invalid. */
4689        ServicePtrs[iService]->valid = True;
4690
4691        /* Set the service as a valid usershare. */
4692        ServicePtrs[iService]->usershare = USERSHARE_VALID;
4693
4694        /* Set guest access. */
4695        if (lp_usershare_allow_guests()) {
4696                ServicePtrs[iService]->bGuest_ok = guest_ok;
4697        }
4698
4699        /* And note when it was loaded. */
4700        ServicePtrs[iService]->usershare_last_mod = sbuf.st_mtime;
4701        string_set(&ServicePtrs[iService]->szPath, sharepath);
4702        string_set(&ServicePtrs[iService]->comment, comment);
4703
4704        return iService;
4705}
4706
4707/***************************************************************************
4708 Checks if a usershare entry has been modified since last load.
4709***************************************************************************/
4710
4711static BOOL usershare_exists(int iService, time_t *last_mod)
4712{
4713        SMB_STRUCT_STAT lsbuf;
4714        const char *usersharepath = Globals.szUsersharePath;
4715        pstring fname;
4716
4717        pstrcpy(fname, usersharepath);
4718        pstrcat(fname, "/");
4719        pstrcat(fname, ServicePtrs[iService]->szService);
4720
4721        if (sys_lstat(fname, &lsbuf) != 0) {
4722                return False;
4723        }
4724
4725        if (!S_ISREG(lsbuf.st_mode)) {
4726                return False;
4727        }
4728
4729        *last_mod = lsbuf.st_mtime;
4730        return True;
4731}
4732
4733/***************************************************************************
4734 Load a usershare service by name. Returns a valid servicenumber or -1.
4735***************************************************************************/
4736
4737int load_usershare_service(const char *servicename)
4738{
4739        SMB_STRUCT_STAT sbuf;
4740        const char *usersharepath = Globals.szUsersharePath;
4741        int max_user_shares = Globals.iUsershareMaxShares;
4742        int snum_template = -1;
4743
4744        if (*usersharepath == 0 ||  max_user_shares == 0) {
4745                return -1;
4746        }
4747
4748        if (sys_stat(usersharepath, &sbuf) != 0) {
4749                DEBUG(0,("load_usershare_service: stat of %s failed. %s\n",
4750                        usersharepath, strerror(errno) ));
4751                return -1;
4752        }
4753
4754        if (!S_ISDIR(sbuf.st_mode)) {
4755                DEBUG(0,("load_usershare_service: %s is not a directory.\n",
4756                        usersharepath ));
4757                return -1;
4758        }
4759
4760        /*
4761         * This directory must be owned by root, and have the 't' bit set.
4762         * It also must not be writable by "other".
4763         */
4764
4765#ifdef S_ISVTX
4766        if (sbuf.st_uid != 0 || !(sbuf.st_mode & S_ISVTX) || (sbuf.st_mode & S_IWOTH)) {
4767#else
4768        if (sbuf.st_uid != 0 || (sbuf.st_mode & S_IWOTH)) {
4769#endif
4770                DEBUG(0,("load_usershare_service: directory %s is not owned by root "
4771                        "or does not have the sticky bit 't' set or is writable by anyone.\n",
4772                        usersharepath ));
4773                return -1;
4774        }
4775
4776        /* Ensure the template share exists if it's set. */
4777        if (Globals.szUsershareTemplateShare[0]) {
4778                /* We can't use lp_servicenumber here as we are recommending that
4779                   template shares have -valid=False set. */
4780                for (snum_template = iNumServices - 1; snum_template >= 0; snum_template--) {
4781                        if (ServicePtrs[snum_template]->szService &&
4782                                        strequal(ServicePtrs[snum_template]->szService,
4783                                                Globals.szUsershareTemplateShare)) {
4784                                break;
4785                        }
4786                }
4787
4788                if (snum_template == -1) {
4789                        DEBUG(0,("load_usershare_service: usershare template share %s "
4790                                "does not exist.\n",
4791                                Globals.szUsershareTemplateShare ));
4792                        return -1;
4793                }
4794        }
4795
4796        return process_usershare_file(usersharepath, servicename, snum_template);
4797}
4798
4799/***************************************************************************
4800 Load all user defined shares from the user share directory.
4801 We only do this if we're enumerating the share list.
4802 This is the function that can delete usershares that have
4803 been removed.
4804***************************************************************************/
4805
4806int load_usershare_shares(void)
4807{
4808        SMB_STRUCT_DIR *dp;
4809        SMB_STRUCT_STAT sbuf;
4810        SMB_STRUCT_DIRENT *de;
4811        int num_usershares = 0;
4812        int max_user_shares = Globals.iUsershareMaxShares;
4813        unsigned int num_dir_entries, num_bad_dir_entries, num_tmp_dir_entries;
4814        unsigned int allowed_bad_entries = ((2*max_user_shares)/10);
4815        unsigned int allowed_tmp_entries = ((2*max_user_shares)/10);
4816        int iService;
4817        int snum_template = -1;
4818        const char *usersharepath = Globals.szUsersharePath;
4819        int ret = lp_numservices();
4820
4821        if (max_user_shares == 0 || *usersharepath == '\0') {
4822                return lp_numservices();
4823        }
4824
4825        if (sys_stat(usersharepath, &sbuf) != 0) {
4826                DEBUG(0,("load_usershare_shares: stat of %s failed. %s\n",
4827                        usersharepath, strerror(errno) ));
4828                return ret;
4829        }
4830
4831        /*
4832         * This directory must be owned by root, and have the 't' bit set.
4833         * It also must not be writable by "other".
4834         */
4835
4836#ifdef S_ISVTX
4837        if (sbuf.st_uid != 0 || !(sbuf.st_mode & S_ISVTX) || (sbuf.st_mode & S_IWOTH)) {
4838#else
4839        if (sbuf.st_uid != 0 || (sbuf.st_mode & S_IWOTH)) {
4840#endif
4841                DEBUG(0,("load_usershare_shares: directory %s is not owned by root "
4842                        "or does not have the sticky bit 't' set or is writable by anyone.\n",
4843                        usersharepath ));
4844                return ret;
4845        }
4846
4847        /* Ensure the template share exists if it's set. */
4848        if (Globals.szUsershareTemplateShare[0]) {
4849                /* We can't use lp_servicenumber here as we are recommending that
4850                   template shares have -valid=False set. */
4851                for (snum_template = iNumServices - 1; snum_template >= 0; snum_template--) {
4852                        if (ServicePtrs[snum_template]->szService &&
4853                                        strequal(ServicePtrs[snum_template]->szService,
4854                                                Globals.szUsershareTemplateShare)) {
4855                                break;
4856                        }
4857                }
4858
4859                if (snum_template == -1) {
4860                        DEBUG(0,("load_usershare_shares: usershare template share %s "
4861                                "does not exist.\n",
4862                                Globals.szUsershareTemplateShare ));
4863                        return ret;
4864                }
4865        }
4866
4867        /* Mark all existing usershares as pending delete. */
4868        for (iService = iNumServices - 1; iService >= 0; iService--) {
4869                if (VALID(iService) && ServicePtrs[iService]->usershare) {
4870                        ServicePtrs[iService]->usershare = USERSHARE_PENDING_DELETE;
4871                }
4872        }
4873
4874        dp = sys_opendir(usersharepath);
4875        if (!dp) {
4876                DEBUG(0,("load_usershare_shares:: failed to open directory %s. %s\n",
4877                        usersharepath, strerror(errno) ));
4878                return ret;
4879        }
4880
4881        for (num_dir_entries = 0, num_bad_dir_entries = 0, num_tmp_dir_entries = 0;
4882                        (de = sys_readdir(dp));
4883                        num_dir_entries++ ) {
4884                int r;
4885                const char *n = de->d_name;
4886
4887                /* Ignore . and .. */
4888                if (*n == '.') {
4889                        if ((n[1] == '\0') || (n[1] == '.' && n[2] == '\0')) {
4890                                continue;
4891                        }
4892                }
4893
4894                if (n[0] == ':') {
4895                        /* Temporary file used when creating a share. */
4896                        num_tmp_dir_entries++;
4897                }
4898
4899                /* Allow 20% tmp entries. */
4900                if (num_tmp_dir_entries > allowed_tmp_entries) {
4901                        DEBUG(0,("load_usershare_shares: too many temp entries (%u) "
4902                                "in directory %s\n",
4903                                num_tmp_dir_entries, usersharepath));
4904                        break;
4905                }
4906
4907                r = process_usershare_file(usersharepath, n, snum_template);
4908                if (r == 0) {
4909                        /* Update the services count. */
4910                        num_usershares++;
4911                        if (num_usershares >= max_user_shares) {
4912                                DEBUG(0,("load_usershare_shares: max user shares reached "
4913                                        "on file %s in directory %s\n",
4914                                        n, usersharepath ));
4915                                break;
4916                        }
4917                } else if (r == -1) {
4918                        num_bad_dir_entries++;
4919                }
4920
4921                /* Allow 20% bad entries. */
4922                if (num_bad_dir_entries > allowed_bad_entries) {
4923                        DEBUG(0,("load_usershare_shares: too many bad entries (%u) "
4924                                "in directory %s\n",
4925                                num_bad_dir_entries, usersharepath));
4926                        break;
4927                }
4928
4929                /* Allow 20% bad entries. */
4930                if (num_dir_entries > max_user_shares + allowed_bad_entries) {
4931                        DEBUG(0,("load_usershare_shares: too many total entries (%u) "
4932                        "in directory %s\n",
4933                        num_dir_entries, usersharepath));
4934                        break;
4935                }
4936        }
4937
4938        sys_closedir(dp);
4939
4940        /* Sweep through and delete any non-refreshed usershares that are
4941           not currently in use. */
4942        for (iService = iNumServices - 1; iService >= 0; iService--) {
4943                if (VALID(iService) && (ServicePtrs[iService]->usershare == USERSHARE_PENDING_DELETE)) {
4944                        if (conn_snum_used(iService)) {
4945                                continue;
4946                        }
4947                        /* Remove from the share ACL db. */
4948                        DEBUG(10,("load_usershare_shares: Removing deleted usershare %s\n",
4949                                lp_servicename(iService) ));
4950                        delete_share_security(snum2params_static(iService));
4951                        free_service_byindex(iService);
4952                }
4953        }
4954
4955        return lp_numservices();
4956}
4957
4958/********************************************************
4959 Destroy global resources allocated in this file
4960********************************************************/
4961
4962void gfree_loadparm(void)
4963{
4964        struct file_lists *f;
4965        struct file_lists *next;
4966        int i;
4967
4968        lp_TALLOC_FREE();
4969
4970        /* Free the file lists */
4971
4972        f = file_lists;
4973        while( f ) {
4974                next = f->next;
4975                SAFE_FREE( f->name );
4976                SAFE_FREE( f->subfname );
4977                SAFE_FREE( f );
4978                f = next;
4979        }
4980
4981        /* Free resources allocated to services */
4982
4983        for ( i = 0; i < iNumServices; i++ ) {
4984                if ( VALID(i) ) {
4985                        free_service_byindex(i);
4986                }
4987        }
4988
4989        SAFE_FREE( ServicePtrs );
4990        iNumServices = 0;
4991
4992        /* Now release all resources allocated to global
4993           parameters and the default service */
4994
4995        for (i = 0; parm_table[i].label; i++) 
4996        {
4997                if ( parm_table[i].type == P_STRING
4998                        || parm_table[i].type == P_USTRING ) 
4999                {
5000                        string_free( (char**)parm_table[i].ptr );
5001                }
5002                else if (parm_table[i].type == P_LIST) {
5003                        str_list_free( (char***)parm_table[i].ptr );
5004                }
5005        }
5006}
5007
5008/***************************************************************************
5009 Load the services array from the services file. Return True on success,
5010 False on failure.
5011***************************************************************************/
5012
5013BOOL lp_load(const char *pszFname,
5014             BOOL global_only,
5015             BOOL save_defaults,
5016             BOOL add_ipc,
5017             BOOL initialize_globals)
5018{
5019        pstring n2;
5020        BOOL bRetval;
5021        param_opt_struct *data, *pdata;
5022
5023        pstrcpy(n2, pszFname);
5024       
5025        standard_sub_basic( get_current_username(), current_user_info.domain,
5026                            n2,sizeof(n2) );
5027
5028        add_to_file_list(pszFname, n2);
5029
5030        bRetval = False;
5031
5032        DEBUG(3, ("lp_load: refreshing parameters\n"));
5033       
5034        bInGlobalSection = True;
5035        bGlobalOnly = global_only;
5036
5037        init_globals(! initialize_globals);
5038        debug_init();
5039
5040        if (save_defaults) {
5041                init_locals();
5042                lp_save_defaults();
5043        }
5044
5045        if (Globals.param_opt != NULL) {
5046                data = Globals.param_opt;
5047                while (data) {
5048                        string_free(&data->key);
5049                        string_free(&data->value);
5050                        str_list_free(&data->list);
5051                        pdata = data->next;
5052                        SAFE_FREE(data);
5053                        data = pdata;
5054                }
5055                Globals.param_opt = NULL;
5056        }
5057       
5058        /* We get sections first, so have to start 'behind' to make up */
5059        iServiceIndex = -1;
5060        bRetval = pm_process(n2, do_section, do_parameter);
5061
5062        /* finish up the last section */
5063        DEBUG(4, ("pm_process() returned %s\n", BOOLSTR(bRetval)));
5064        if (bRetval)
5065                if (iServiceIndex >= 0)
5066                        bRetval = service_ok(iServiceIndex);
5067
5068        lp_add_auto_services(lp_auto_services());
5069
5070        if (add_ipc) {
5071                /* When 'restrict anonymous = 2' guest connections to ipc$
5072                   are denied */
5073                lp_add_ipc("IPC$", (lp_restrict_anonymous() < 2));
5074                if ( lp_enable_asu_support() )
5075                        lp_add_ipc("ADMIN$", False);
5076        }
5077
5078        set_server_role();
5079        set_default_server_announce_type();
5080        set_allowed_client_auth();
5081
5082        bLoaded = True;
5083
5084        /* Now we check bWINSsupport and set szWINSserver to 127.0.0.1 */
5085        /* if bWINSsupport is true and we are in the client            */
5086        if (in_client && Globals.bWINSsupport) {
5087                lp_do_parameter(GLOBAL_SECTION_SNUM, "wins server", "127.0.0.1");
5088        }
5089
5090        init_iconv();
5091
5092        return (bRetval);
5093}
5094
5095/***************************************************************************
5096 Reset the max number of services.
5097***************************************************************************/
5098
5099void lp_resetnumservices(void)
5100{
5101        iNumServices = 0;
5102}
5103
5104/***************************************************************************
5105 Return the max number of services.
5106***************************************************************************/
5107
5108int lp_numservices(void)
5109{
5110        return (iNumServices);
5111}
5112
5113/***************************************************************************
5114Display the contents of the services array in human-readable form.
5115***************************************************************************/
5116
5117void lp_dump(FILE *f, BOOL show_defaults, int maxtoprint)
5118{
5119        int iService;
5120
5121        if (show_defaults)
5122                defaults_saved = False;
5123
5124        dump_globals(f);
5125
5126        dump_a_service(&sDefault, f);
5127
5128        for (iService = 0; iService < maxtoprint; iService++) {
5129                fprintf(f,"\n");
5130                lp_dump_one(f, show_defaults, iService);
5131        }
5132}
5133
5134/***************************************************************************
5135Display the contents of one service in human-readable form.
5136***************************************************************************/
5137
5138void lp_dump_one(FILE * f, BOOL show_defaults, int snum)
5139{
5140        if (VALID(snum)) {
5141                if (ServicePtrs[snum]->szService[0] == '\0')
5142                        return;
5143                dump_a_service(ServicePtrs[snum], f);
5144        }
5145}
5146
5147/***************************************************************************
5148Return the number of the service with the given name, or -1 if it doesn't
5149exist. Note that this is a DIFFERENT ANIMAL from the internal function
5150getservicebyname()! This works ONLY if all services have been loaded, and
5151does not copy the found service.
5152***************************************************************************/
5153
5154int lp_servicenumber(const char *pszServiceName)
5155{
5156        int iService;
5157        fstring serviceName;
5158       
5159        if (!pszServiceName) {
5160                return GLOBAL_SECTION_SNUM;
5161        }
5162       
5163        for (iService = iNumServices - 1; iService >= 0; iService--) {
5164                if (VALID(iService) && ServicePtrs[iService]->szService) {
5165                        /*
5166                         * The substitution here is used to support %U is
5167                         * service names
5168                         */
5169                        fstrcpy(serviceName, ServicePtrs[iService]->szService);
5170                        standard_sub_basic(get_current_username(),
5171                                           current_user_info.domain,
5172                                           serviceName,sizeof(serviceName));
5173                        if (strequal(serviceName, pszServiceName)) {
5174                                break;
5175                        }
5176                }
5177        }
5178
5179        if (iService >= 0 && ServicePtrs[iService]->usershare == USERSHARE_VALID) {
5180                time_t last_mod;
5181
5182                if (!usershare_exists(iService, &last_mod)) {
5183                        /* Remove the share security tdb entry for it. */
5184                        delete_share_security(snum2params_static(iService));
5185                        /* Remove it from the array. */
5186                        free_service_byindex(iService);
5187                        /* Doesn't exist anymore. */
5188                        return GLOBAL_SECTION_SNUM;
5189                }
5190
5191                /* Has it been modified ? If so delete and reload. */
5192                if (ServicePtrs[iService]->usershare_last_mod < last_mod) {
5193                        /* Remove it from the array. */
5194                        free_service_byindex(iService);
5195                        /* and now reload it. */
5196                        iService = load_usershare_service(pszServiceName);
5197                }
5198        }
5199
5200        if (iService < 0) {
5201                DEBUG(7,("lp_servicenumber: couldn't find %s\n", pszServiceName));
5202                return GLOBAL_SECTION_SNUM;
5203        }
5204
5205        return (iService);
5206}
5207
5208BOOL share_defined(const char *service_name)
5209{
5210        return (lp_servicenumber(service_name) != -1);
5211}
5212
5213struct share_params *get_share_params(TALLOC_CTX *mem_ctx,
5214                                      const char *sharename)
5215{
5216        struct share_params *result;
5217        char *sname;
5218        int snum;
5219
5220        if (!(sname = SMB_STRDUP(sharename))) {
5221                return NULL;
5222        }
5223
5224        snum = find_service(sname);
5225        SAFE_FREE(sname);
5226
5227        if (snum < 0) {
5228                return NULL;
5229        }
5230
5231        if (!(result = TALLOC_P(mem_ctx, struct share_params))) {
5232                DEBUG(0, ("talloc failed\n"));
5233                return NULL;
5234        }
5235
5236        result->service = snum;
5237        return result;
5238}
5239
5240struct share_iterator *share_list_all(TALLOC_CTX *mem_ctx)
5241{
5242        struct share_iterator *result;
5243
5244        if (!(result = TALLOC_P(mem_ctx, struct share_iterator))) {
5245                DEBUG(0, ("talloc failed\n"));
5246                return NULL;
5247        }
5248
5249        result->next_id = 0;
5250        return result;
5251}
5252
5253struct share_params *next_share(struct share_iterator *list)
5254{
5255        struct share_params *result;
5256
5257        while (!lp_snum_ok(list->next_id) &&
5258               (list->next_id < lp_numservices())) {
5259                list->next_id += 1;
5260        }
5261
5262        if (list->next_id >= lp_numservices()) {
5263                return NULL;
5264        }
5265
5266        if (!(result = TALLOC_P(list, struct share_params))) {
5267                DEBUG(0, ("talloc failed\n"));
5268                return NULL;
5269        }
5270
5271        result->service = list->next_id;
5272        list->next_id += 1;
5273        return result;
5274}
5275
5276struct share_params *next_printer(struct share_iterator *list)
5277{
5278        struct share_params *result;
5279
5280        while ((result = next_share(list)) !=