diff options
Diffstat (limited to 'source/param')
-rw-r--r-- | source/param/loadparm.c | 2019 | ||||
-rw-r--r-- | source/param/params.c | 326 |
2 files changed, 2345 insertions, 0 deletions
diff --git a/source/param/loadparm.c b/source/param/loadparm.c new file mode 100644 index 00000000000..b368d3b2fa9 --- /dev/null +++ b/source/param/loadparm.c @@ -0,0 +1,2019 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + Parameter loading functions + Copyright (C) Karl Auer 1993,1997 + + Largely re-written by Andrew Tridgell, September 1994 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* + * Load parameters. + * + * This module provides suitable callback functions for the params + * module. It builds the internal table of service details which is + * then used by the rest of the server. + * + * To add a parameter: + * + * 1) add it to the global or service structure definition + * 2) add it to the parm_table + * 3) add it to the list of available functions (eg: using FN_GLOBAL_STRING()) + * 4) If it's a global then initialise it in init_globals. If a local + * (ie. service) parameter then initialise it in the sDefault structure + * + * + * Notes: + * The configuration file is processed sequentially for speed. It is NOT + * accessed randomly as happens in 'real' Windows. For this reason, there + * is a fair bit of sequence-dependent code here - ie., code which assumes + * that certain things happen before others. In particular, the code which + * happens at the boundary between sections is delicately poised, so be + * careful! + * + */ + +#include "includes.h" + +BOOL bLoaded = False; + +extern int DEBUGLEVEL; +extern pstring user_socket_options; +extern pstring myname; + +#ifndef GLOBAL_NAME +#define GLOBAL_NAME "global" +#endif + +#ifndef PRINTCAP_NAME +#ifdef AIX +#define PRINTCAP_NAME "/etc/qconfig" +#else +#define PRINTCAP_NAME "/etc/printcap" +#endif +#endif + +#ifndef PRINTERS_NAME +#define PRINTERS_NAME "printers" +#endif + +#ifndef HOMES_NAME +#define HOMES_NAME "homes" +#endif + +/* some helpful bits */ +#define pSERVICE(i) ServicePtrs[i] +#define iSERVICE(i) (*pSERVICE(i)) +#define LP_SNUM_OK(iService) (((iService) >= 0) && ((iService) < iNumServices) && iSERVICE(iService).valid) +#define VALID(i) iSERVICE(i).valid + +/* these are the types of parameter we have */ +typedef enum +{ + P_BOOL,P_BOOLREV,P_CHAR,P_INTEGER,P_OCTAL, + P_STRING,P_USTRING,P_GSTRING,P_UGSTRING +} parm_type; + +typedef enum +{ + P_LOCAL,P_GLOBAL,P_NONE +} parm_class; + +int keepalive=0; +extern BOOL use_getwd_cache; + +extern int extra_time_offset; +#ifdef KANJI +extern int coding_system; +#endif + +/* + * This structure describes global (ie., server-wide) parameters. + */ +typedef struct +{ + char *szPrintcapname; + char *szLockDir; + char *szRootdir; + char *szDefaultService; + char *szDfree; + char *szMsgCommand; + char *szHostsEquiv; + char *szServerString; + char *szAutoServices; + char *szPasswdProgram; + char *szPasswdChat; + char *szLogFile; + char *szConfigFile; + char *szSMBPasswdFile; + char *szPasswordServer; + char *szSocketOptions; + char *szValidChars; + char *szWorkGroup; + char *szDomainController; + char *szUsernameMap; + char *szCharacterSet; + char *szLogonScript; + char *szLogonPath; + char *szVetoFiles; + char *szSmbrun; + char *szWINSserver; + char *szInterfaces; + char *szRemoteAnnounce; + char *szSocketAddress; + char *szNISHomeMapName; + int max_log_size; + int mangled_stack; + int max_xmit; + int max_mux; + int max_packet; + int pwordlevel; + int deadtime; + int maxprotocol; + int security; + int printing; + int maxdisksize; + int lpqcachetime; + int syslog; + int os_level; + int max_ttl; + int ReadSize; + int shmem_size; + int shmem_hash_size; + BOOL bWINSsupport; + BOOL bWINSproxy; + BOOL bLocalMaster; + BOOL bPreferredMaster; + BOOL bDomainMaster; + BOOL bDomainLogons; + BOOL bEncryptPasswords; + BOOL bStripDot; + BOOL bNullPasswords; + BOOL bLoadPrinters; + BOOL bUseRhosts; + BOOL bReadRaw; + BOOL bWriteRaw; + BOOL bReadPrediction; + BOOL bReadbmpx; + BOOL bSyslogOnly; + BOOL bBrowseList; + BOOL bUnixRealname; + BOOL bNISHomeMap; +} global; + +static global Globals; + + + +/* + * This structure describes a single service. + */ +typedef struct +{ + BOOL valid; + char *szService; + char *szPath; + char *szUsername; + char *szGuestaccount; + char *szInvalidUsers; + char *szValidUsers; + char *szAdminUsers; + char *szCopy; + char *szInclude; + char *szPreExec; + char *szPostExec; + char *szRootPreExec; + char *szRootPostExec; + char *szPrintcommand; + char *szLpqcommand; + char *szLprmcommand; + char *szLppausecommand; + char *szLpresumecommand; + char *szPrintername; + char *szPrinterDriver; + char *szDontdescend; + char *szHostsallow; + char *szHostsdeny; + char *szMagicScript; + char *szMagicOutput; + char *szMangledMap; + char *comment; + char *force_user; + char *force_group; + char *readlist; + char *writelist; + char *volume; + int iMinPrintSpace; + int iCreate_mode; + int iDir_mode; + int iMaxConnections; + int iDefaultCase; + BOOL bAlternatePerm; + BOOL bRevalidate; + BOOL bCaseSensitive; + BOOL bCasePreserve; + BOOL bShortCasePreserve; + BOOL bCaseMangle; + BOOL status; + BOOL bHideDotFiles; + BOOL bBrowseable; + BOOL bAvailable; + BOOL bRead_only; + BOOL bNo_set_dir; + BOOL bGuest_only; + BOOL bGuest_ok; + BOOL bPrint_ok; + BOOL bPostscript; + BOOL bMap_system; + BOOL bMap_hidden; + BOOL bMap_archive; + BOOL bLocking; + BOOL bStrictLocking; + BOOL bShareModes; + BOOL bOnlyUser; + BOOL bMangledNames; + BOOL bWidelinks; + BOOL bSyncAlways; + char magic_char; + BOOL *copymap; + BOOL bDeleteReadonly; + BOOL bFakeOplocks; + char dummy[3]; /* for alignment */ +} service; + + +/* This is a default service used to prime a services structure */ +static service sDefault = +{ + True, /* valid */ + NULL, /* szService */ + NULL, /* szPath */ + NULL, /* szUsername */ + NULL, /* szGuestAccount */ + NULL, /* szInvalidUsers */ + NULL, /* szValidUsers */ + NULL, /* szAdminUsers */ + NULL, /* szCopy */ + NULL, /* szInclude */ + NULL, /* szPreExec */ + NULL, /* szPostExec */ + NULL, /* szRootPreExec */ + NULL, /* szRootPostExec */ + NULL, /* szPrintcommand */ + NULL, /* szLpqcommand */ + NULL, /* szLprmcommand */ + NULL, /* szLppausecommand */ + NULL, /* szLpresumecommand */ + NULL, /* szPrintername */ + NULL, /* szPrinterDriver */ + NULL, /* szDontdescend */ + NULL, /* szHostsallow */ + NULL, /* szHostsdeny */ + NULL, /* szMagicScript */ + NULL, /* szMagicOutput */ + NULL, /* szMangledMap */ + NULL, /* comment */ + NULL, /* force user */ + NULL, /* force group */ + NULL, /* readlist */ + NULL, /* writelist */ + NULL, /* volume */ + 0, /* iMinPrintSpace */ + 0644, /* iCreate_mode */ + 0755, /* iDir_mode */ + 0, /* iMaxConnections */ + CASE_LOWER, /* iDefaultCase */ + False, /* bAlternatePerm */ + False, /* revalidate */ + False, /* case sensitive */ + False, /* case preserve */ + False, /* short case preserve */ + False, /* case mangle */ + True, /* status */ + True, /* bHideDotFiles */ + True, /* bBrowseable */ + True, /* bAvailable */ + True, /* bRead_only */ + True, /* bNo_set_dir */ + False, /* bGuest_only */ + False, /* bGuest_ok */ + False, /* bPrint_ok */ + False, /* bPostscript */ + False, /* bMap_system */ + False, /* bMap_hidden */ + True, /* bMap_archive */ + True, /* bLocking */ + False, /* bStrictLocking */ + True, /* bShareModes */ + False, /* bOnlyUser */ + True, /* bMangledNames */ + True, /* bWidelinks */ + False, /* bSyncAlways */ + '~', /* magic char */ + NULL, /* copymap */ + False, /* bDeleteReadonly */ + False, /* bFakeOplocks */ + "" /* dummy */ +}; + + + +/* local variables */ +static service **ServicePtrs = NULL; +static int iNumServices = 0; +static int iServiceIndex = 0; +static BOOL bInGlobalSection = True; +static BOOL bGlobalOnly = False; + + +#define NUMPARAMETERS (sizeof(parm_table) / sizeof(struct parm_struct)) + +/* prototypes for the special type handlers */ +static BOOL handle_valid_chars(char *pszParmValue, char **ptr); +static BOOL handle_include(char *pszParmValue, char **ptr); +static BOOL handle_copy(char *pszParmValue, char **ptr); +static BOOL handle_protocol(char *pszParmValue,int *val); +static BOOL handle_security(char *pszParmValue,int *val); +static BOOL handle_case(char *pszParmValue,int *val); +static BOOL handle_printing(char *pszParmValue,int *val); +static BOOL handle_character_set(char *pszParmValue,int *val); +#ifdef KANJI +static BOOL handle_coding_system(char *pszParmValue,int *val); +#endif /* KANJI */ + +struct parm_struct +{ + char *label; + parm_type type; + parm_class class; + void *ptr; + BOOL (*special)(); +} parm_table[] = +{ + {"debuglevel", P_INTEGER, P_GLOBAL, &DEBUGLEVEL, NULL}, + {"log level", P_INTEGER, P_GLOBAL, &DEBUGLEVEL, NULL}, + {"syslog", P_INTEGER, P_GLOBAL, &Globals.syslog, NULL}, + {"syslog only", P_BOOL, P_GLOBAL, &Globals.bSyslogOnly, NULL}, + {"protocol", P_INTEGER, P_GLOBAL, &Globals.maxprotocol,handle_protocol}, + {"security", P_INTEGER, P_GLOBAL, &Globals.security,handle_security}, + {"printing", P_INTEGER, P_GLOBAL, &Globals.printing,handle_printing}, + {"max disk size", P_INTEGER, P_GLOBAL, &Globals.maxdisksize, NULL}, + {"lpq cache time", P_INTEGER, P_GLOBAL, &Globals.lpqcachetime, NULL}, + {"encrypt passwords",P_BOOL, P_GLOBAL, &Globals.bEncryptPasswords, NULL}, + {"getwd cache", P_BOOL, P_GLOBAL, &use_getwd_cache, NULL}, + {"read prediction", P_BOOL, P_GLOBAL, &Globals.bReadPrediction, NULL}, + {"read bmpx", P_BOOL, P_GLOBAL, &Globals.bReadbmpx, NULL}, + {"read raw", P_BOOL, P_GLOBAL, &Globals.bReadRaw, NULL}, + {"write raw", P_BOOL, P_GLOBAL, &Globals.bWriteRaw, NULL}, + {"use rhosts", P_BOOL, P_GLOBAL, &Globals.bUseRhosts, NULL}, + {"load printers", P_BOOL, P_GLOBAL, &Globals.bLoadPrinters, NULL}, + {"null passwords", P_BOOL, P_GLOBAL, &Globals.bNullPasswords, NULL}, + {"strip dot", P_BOOL, P_GLOBAL, &Globals.bStripDot, NULL}, + {"interfaces", P_STRING, P_GLOBAL, &Globals.szInterfaces, NULL}, + {"password server", P_STRING, P_GLOBAL, &Globals.szPasswordServer, NULL}, + {"socket options", P_GSTRING, P_GLOBAL, user_socket_options, NULL}, + {"netbios name", P_UGSTRING,P_GLOBAL, myname, NULL}, + {"smbrun", P_STRING, P_GLOBAL, &Globals.szSmbrun, NULL}, + {"veto files", P_STRING, P_GLOBAL, &Globals.szVetoFiles, NULL}, + {"log file", P_STRING, P_GLOBAL, &Globals.szLogFile, NULL}, + {"config file", P_STRING, P_GLOBAL, &Globals.szConfigFile, NULL}, + {"smb passwd file", P_STRING, P_GLOBAL, &Globals.szSMBPasswdFile, NULL}, + {"hosts equiv", P_STRING, P_GLOBAL, &Globals.szHostsEquiv, NULL}, + {"preload", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL}, + {"auto services", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL}, + {"server string", P_STRING, P_GLOBAL, &Globals.szServerString, NULL}, + {"printcap name", P_STRING, P_GLOBAL, &Globals.szPrintcapname, NULL}, + {"printcap", P_STRING, P_GLOBAL, &Globals.szPrintcapname, NULL}, + {"lock dir", P_STRING, P_GLOBAL, &Globals.szLockDir, NULL}, + {"lock directory", P_STRING, P_GLOBAL, &Globals.szLockDir, NULL}, + {"root directory", P_STRING, P_GLOBAL, &Globals.szRootdir, NULL}, + {"root dir", P_STRING, P_GLOBAL, &Globals.szRootdir, NULL}, + {"root", P_STRING, P_GLOBAL, &Globals.szRootdir, NULL}, + {"default service", P_STRING, P_GLOBAL, &Globals.szDefaultService, NULL}, + {"default", P_STRING, P_GLOBAL, &Globals.szDefaultService, NULL}, + {"message command", P_STRING, P_GLOBAL, &Globals.szMsgCommand, NULL}, + {"dfree command", P_STRING, P_GLOBAL, &Globals.szDfree, NULL}, + {"passwd program", P_STRING, P_GLOBAL, &Globals.szPasswdProgram, NULL}, + {"passwd chat", P_STRING, P_GLOBAL, &Globals.szPasswdChat, NULL}, + {"valid chars", P_STRING, P_GLOBAL, &Globals.szValidChars, handle_valid_chars}, + {"workgroup", P_USTRING, P_GLOBAL, &Globals.szWorkGroup, NULL}, + {"domain controller",P_STRING, P_GLOBAL, &Globals.szDomainController,NULL}, + {"username map", P_STRING, P_GLOBAL, &Globals.szUsernameMap, NULL}, + {"character set", P_STRING, P_GLOBAL, &Globals.szCharacterSet, handle_character_set}, + {"logon script", P_STRING, P_GLOBAL, &Globals.szLogonScript, NULL}, + {"logon path", P_STRING, P_GLOBAL, &Globals.szLogonPath, NULL}, + {"remote announce", P_STRING, P_GLOBAL, &Globals.szRemoteAnnounce, NULL}, + {"socket address", P_STRING, P_GLOBAL, &Globals.szSocketAddress, NULL}, + {"homedir map", P_STRING, P_GLOBAL, &Globals.szNISHomeMapName, NULL}, + {"max log size", P_INTEGER, P_GLOBAL, &Globals.max_log_size, NULL}, + {"mangled stack", P_INTEGER, P_GLOBAL, &Globals.mangled_stack, NULL}, + {"max mux", P_INTEGER, P_GLOBAL, &Globals.max_mux, NULL}, + {"max xmit", P_INTEGER, P_GLOBAL, &Globals.max_xmit, NULL}, + {"max packet", P_INTEGER, P_GLOBAL, &Globals.max_packet, NULL}, + {"packet size", P_INTEGER, P_GLOBAL, &Globals.max_packet, NULL}, + {"password level", P_INTEGER, P_GLOBAL, &Globals.pwordlevel, NULL}, + {"keepalive", P_INTEGER, P_GLOBAL, &keepalive, NULL}, + {"deadtime", P_INTEGER, P_GLOBAL, &Globals.deadtime, NULL}, + {"time offset", P_INTEGER, P_GLOBAL, &extra_time_offset, NULL}, + {"read size", P_INTEGER, P_GLOBAL, &Globals.ReadSize, NULL}, + {"shared mem size", P_INTEGER, P_GLOBAL, &Globals.shmem_size, NULL}, + {"shared file entries", P_INTEGER, P_GLOBAL, &Globals.shmem_hash_size, NULL}, +#ifdef KANJI + {"coding system", P_INTEGER, P_GLOBAL, &coding_system, handle_coding_system}, +#endif /* KANJI */ + {"os level", P_INTEGER, P_GLOBAL, &Globals.os_level, NULL}, + {"max ttl", P_INTEGER, P_GLOBAL, &Globals.max_ttl, NULL}, + {"wins support", P_BOOL, P_GLOBAL, &Globals.bWINSsupport, NULL}, + {"wins proxy", P_BOOL, P_GLOBAL, &Globals.bWINSproxy, NULL}, + {"wins server", P_STRING, P_GLOBAL, &Globals.szWINSserver, NULL}, + {"preferred master", P_BOOL, P_GLOBAL, &Globals.bPreferredMaster, NULL}, + {"prefered master", P_BOOL, P_GLOBAL, &Globals.bPreferredMaster, NULL}, + {"local master", P_BOOL, P_GLOBAL, &Globals.bLocalMaster, NULL}, + {"domain master", P_BOOL, P_GLOBAL, &Globals.bDomainMaster, NULL}, + {"domain logons", P_BOOL, P_GLOBAL, &Globals.bDomainLogons, NULL}, + {"browse list", P_BOOL, P_GLOBAL, &Globals.bBrowseList, NULL}, + {"unix realname", P_BOOL, P_GLOBAL, &Globals.bUnixRealname, NULL}, + {"NIS homedir", P_BOOL, P_GLOBAL, &Globals.bNISHomeMap, NULL}, + {"-valid", P_BOOL, P_LOCAL, &sDefault.valid, NULL}, + {"comment", P_STRING, P_LOCAL, &sDefault.comment, NULL}, + {"copy", P_STRING, P_LOCAL, &sDefault.szCopy, handle_copy}, + {"include", P_STRING, P_LOCAL, &sDefault.szInclude, handle_include}, + {"exec", P_STRING, P_LOCAL, &sDefault.szPreExec, NULL}, + {"preexec", P_STRING, P_LOCAL, &sDefault.szPreExec, NULL}, + {"postexec", P_STRING, P_LOCAL, &sDefault.szPostExec, NULL}, + {"root preexec", P_STRING, P_LOCAL, &sDefault.szRootPreExec, NULL}, + {"root postexec", P_STRING, P_LOCAL, &sDefault.szRootPostExec, NULL}, + {"alternate permissions",P_BOOL,P_LOCAL, &sDefault.bAlternatePerm, NULL}, + {"revalidate", P_BOOL, P_LOCAL, &sDefault.bRevalidate, NULL}, + {"default case", P_INTEGER, P_LOCAL, &sDefault.iDefaultCase, handle_case}, + {"case sensitive", P_BOOL, P_LOCAL, &sDefault.bCaseSensitive, NULL}, + {"casesignames", P_BOOL, P_LOCAL, &sDefault.bCaseSensitive, NULL}, + {"preserve case", P_BOOL, P_LOCAL, &sDefault.bCasePreserve, NULL}, + {"short preserve case",P_BOOL, P_LOCAL, &sDefault.bShortCasePreserve,NULL}, + {"mangle case", P_BOOL, P_LOCAL, &sDefault.bCaseMangle, NULL}, + {"mangling char", P_CHAR, P_LOCAL, &sDefault.magic_char, NULL}, + {"browseable", P_BOOL, P_LOCAL, &sDefault.bBrowseable, NULL}, + {"browsable", P_BOOL, P_LOCAL, &sDefault.bBrowseable, NULL}, + {"available", P_BOOL, P_LOCAL, &sDefault.bAvailable, NULL}, + {"path", P_STRING, P_LOCAL, &sDefault.szPath, NULL}, + {"directory", P_STRING, P_LOCAL, &sDefault.szPath, NULL}, + {"username", P_STRING, P_LOCAL, &sDefault.szUsername, NULL}, + {"user", P_STRING, P_LOCAL, &sDefault.szUsername, NULL}, + {"users", P_STRING, P_LOCAL, &sDefault.szUsername, NULL}, + {"guest account", P_STRING, P_LOCAL, &sDefault.szGuestaccount, NULL}, + {"invalid users", P_STRING, P_LOCAL, &sDefault.szInvalidUsers, NULL}, + {"valid users", P_STRING, P_LOCAL, &sDefault.szValidUsers, NULL}, + {"admin users", P_STRING, P_LOCAL, &sDefault.szAdminUsers, NULL}, + {"read list", P_STRING, P_LOCAL, &sDefault.readlist, NULL}, + {"write list", P_STRING, P_LOCAL, &sDefault.writelist, NULL}, + {"volume", P_STRING, P_LOCAL, &sDefault.volume, NULL}, + {"force user", P_STRING, P_LOCAL, &sDefault.force_user, NULL}, + {"force group", P_STRING, P_LOCAL, &sDefault.force_group, NULL}, + {"group", P_STRING, P_LOCAL, &sDefault.force_group, NULL}, + {"read only", P_BOOL, P_LOCAL, &sDefault.bRead_only, NULL}, + {"write ok", P_BOOLREV, P_LOCAL, &sDefault.bRead_only, NULL}, + {"writeable", P_BOOLREV, P_LOCAL, &sDefault.bRead_only, NULL}, + {"writable", P_BOOLREV, P_LOCAL, &sDefault.bRead_only, NULL}, + {"max connections", P_INTEGER, P_LOCAL, &sDefault.iMaxConnections, NULL}, + {"min print space", P_INTEGER, P_LOCAL, &sDefault.iMinPrintSpace, NULL}, + {"create mask", P_OCTAL, P_LOCAL, &sDefault.iCreate_mode, NULL}, + {"create mode", P_OCTAL, P_LOCAL, &sDefault.iCreate_mode, NULL}, + {"directory mask", P_OCTAL, P_LOCAL, &sDefault.iDir_mode, NULL}, + {"directory mode", P_OCTAL, P_LOCAL, &sDefault.iDir_mode, NULL}, + {"set directory", P_BOOLREV, P_LOCAL, &sDefault.bNo_set_dir, NULL}, + {"status", P_BOOL, P_LOCAL, &sDefault.status, NULL}, + {"hide dot files", P_BOOL, P_LOCAL, &sDefault.bHideDotFiles, NULL}, + {"guest only", P_BOOL, P_LOCAL, &sDefault.bGuest_only, NULL}, + {"only guest", P_BOOL, P_LOCAL, &sDefault.bGuest_only, NULL}, + {"guest ok", P_BOOL, P_LOCAL, &sDefault.bGuest_ok, NULL}, + {"public", P_BOOL, P_LOCAL, &sDefault.bGuest_ok, NULL}, + {"print ok", P_BOOL, P_LOCAL, &sDefault.bPrint_ok, NULL}, + {"printable", P_BOOL, P_LOCAL, &sDefault.bPrint_ok, NULL}, + {"postscript", P_BOOL, P_LOCAL, &sDefault.bPostscript, NULL}, + {"map system", P_BOOL, P_LOCAL, &sDefault.bMap_system, NULL}, + {"map hidden", P_BOOL, P_LOCAL, &sDefault.bMap_hidden, NULL}, + {"map archive", P_BOOL, P_LOCAL, &sDefault.bMap_archive, NULL}, + {"locking", P_BOOL, P_LOCAL, &sDefault.bLocking, NULL}, + {"strict locking", P_BOOL, P_LOCAL, &sDefault.bStrictLocking, NULL}, + {"share modes", P_BOOL, P_LOCAL, &sDefault.bShareModes, NULL}, + {"only user", P_BOOL, P_LOCAL, &sDefault.bOnlyUser, NULL}, + {"wide links", P_BOOL, P_LOCAL, &sDefault.bWidelinks, NULL}, + {"sync always", P_BOOL, P_LOCAL, &sDefault.bSyncAlways, NULL}, + {"mangled names", P_BOOL, P_LOCAL, &sDefault.bMangledNames, NULL}, + {"fake oplocks", P_BOOL, P_LOCAL, &sDefault.bFakeOplocks, NULL}, + {"print command", P_STRING, P_LOCAL, &sDefault.szPrintcommand, NULL}, + {"lpq command", P_STRING, P_LOCAL, &sDefault.szLpqcommand, NULL}, + {"lprm command", P_STRING, P_LOCAL, &sDefault.szLprmcommand, NULL}, + {"lppause command", P_STRING, P_LOCAL, &sDefault.szLppausecommand, NULL}, + {"lpresume command", P_STRING, P_LOCAL, &sDefault.szLpresumecommand,NULL}, + {"printer", P_STRING, P_LOCAL, &sDefault.szPrintername, NULL}, + {"printer name", P_STRING, P_LOCAL, &sDefault.szPrintername, NULL}, + {"printer driver", P_STRING, P_LOCAL, &sDefault.szPrinterDriver, NULL}, + {"hosts allow", P_STRING, P_LOCAL, &sDefault.szHostsallow, NULL}, + {"allow hosts", P_STRING, P_LOCAL, &sDefault.szHostsallow, NULL}, + {"hosts deny", P_STRING, P_LOCAL, &sDefault.szHostsdeny, NULL}, + {"deny hosts", P_STRING, P_LOCAL, &sDefault.szHostsdeny, NULL}, + {"dont descend", P_STRING, P_LOCAL, &sDefault.szDontdescend, NULL}, + {"magic script", P_STRING, P_LOCAL, &sDefault.szMagicScript, NULL}, + {"magic output", P_STRING, P_LOCAL, &sDefault.szMagicOutput, NULL}, + {"mangled map", P_STRING, P_LOCAL, &sDefault.szMangledMap, NULL}, + {"delete readonly", P_BOOL, P_LOCAL, &sDefault.bDeleteReadonly, NULL}, + + {NULL, P_BOOL, P_NONE, NULL, NULL} +}; + + + +/*************************************************************************** +Initialise the global parameter structure. +***************************************************************************/ +static void init_globals(void) +{ + static BOOL done_init = False; + pstring s; + + if (!done_init) + { + int i; + bzero((void *)&Globals,sizeof(Globals)); + + for (i = 0; parm_table[i].label; i++) + if ((parm_table[i].type == P_STRING || + parm_table[i].type == P_USTRING) && + parm_table[i].ptr) + string_init(parm_table[i].ptr,""); + + string_set(&sDefault.szGuestaccount, GUEST_ACCOUNT); + string_set(&sDefault.szPrinterDriver, "NULL"); + + done_init = True; + } + + + DEBUG(3,("Initialising global parameters\n")); + +#ifdef SMB_PASSWD_FILE + string_set(&Globals.szSMBPasswdFile, SMB_PASSWD_FILE); +#endif + string_set(&Globals.szPasswdChat,"*old*password* %o\\n *new*password* %n\\n *new*password* %n\\n *changed*"); + string_set(&Globals.szWorkGroup, WORKGROUP); +#ifdef SMB_PASSWD + string_set(&Globals.szPasswdProgram, SMB_PASSWD); +#else + string_set(&Globals.szPasswdProgram, "/bin/passwd"); +#endif + string_set(&Globals.szPrintcapname, PRINTCAP_NAME); + string_set(&Globals.szLockDir, LOCKDIR); + string_set(&Globals.szRootdir, "/"); + string_set(&Globals.szSmbrun, SMBRUN); + string_set(&Globals.szSocketAddress, "0.0.0.0"); + sprintf(s,"Samba %s",VERSION); + string_set(&Globals.szServerString,s); + Globals.bLoadPrinters = True; + Globals.bUseRhosts = False; + Globals.max_packet = 65535; + Globals.mangled_stack = 50; + Globals.max_xmit = 65535; + Globals.max_mux = 2; + Globals.lpqcachetime = 10; + Globals.pwordlevel = 0; + Globals.deadtime = 0; + Globals.max_log_size = 5000; + Globals.maxprotocol = PROTOCOL_NT1; + Globals.security = SEC_SHARE; + Globals.bEncryptPasswords = False; + Globals.printing = DEFAULT_PRINTING; + Globals.bReadRaw = True; + Globals.bWriteRaw = True; + Globals.bReadPrediction = False; + Globals.bReadbmpx = True; + Globals.bNullPasswords = False; + Globals.bStripDot = False; + Globals.syslog = 1; + Globals.bSyslogOnly = False; + Globals.os_level = 0; + Globals.max_ttl = 60*60*4; /* 2 hours default */ + Globals.ReadSize = 16*1024; + Globals.shmem_size = SHMEM_SIZE; + Globals.shmem_hash_size = SHMEM_HASH_SIZE; + Globals.bUnixRealname = False; +#if (defined(NETGROUP) && defined(AUTOMOUNT)) + Globals.bNISHomeMap = False; + string_set(&Globals.szNISHomeMapName, "auto.home"); +#endif +#ifdef KANJI + coding_system = interpret_coding_system (KANJI, SJIS_CODE); +#endif /* KANJI */ + +/* these parameters are set to defaults that are more appropriate + for the increasing samba install base: + + as a member of the workgroup, that will possibly become a + _local_ master browser (lm = True). this is opposed to a forced + local master browser startup (pm = True). + + doesn't provide WINS server service by default (wsupp = False), + and doesn't provide domain master browser services by default, either. + +*/ + + Globals.bPreferredMaster = False; + Globals.bLocalMaster = True; + Globals.bDomainMaster = False; + Globals.bDomainLogons = False; + Globals.bBrowseList = True; + Globals.bWINSsupport = False; + Globals.bWINSproxy = False; +} + +/*************************************************************************** +check if a string is initialised and if not then initialise it +***************************************************************************/ +static void string_initial(char **s,char *v) +{ + if (!*s || !**s) + string_init(s,v); +} + + +/*************************************************************************** +Initialise the sDefault parameter structure. +***************************************************************************/ +static void init_locals(void) +{ + /* choose defaults depending on the type of printing */ + switch (Globals.printing) + { + case PRINT_BSD: + case PRINT_AIX: + case PRINT_LPRNG: + case PRINT_PLP: + string_initial(&sDefault.szLpqcommand,"lpq -P%p"); + string_initial(&sDefault.szLprmcommand,"lprm -P%p %j"); + string_initial(&sDefault.szPrintcommand,"lpr -r -P%p %s"); + break; + + case PRINT_SYSV: + case PRINT_HPUX: + string_initial(&sDefault.szLpqcommand,"lpstat -o%p"); + string_initial(&sDefault.szLprmcommand,"cancel %p-%j"); + string_initial(&sDefault.szPrintcommand,"lp -c -d%p %s; rm %s"); +#ifdef SVR4 + string_initial(&sDefault.szLppausecommand,"lp -i %p-%j -H hold"); + string_initial(&sDefault.szLpresumecommand,"lp -i %p-%j -H resume"); +#endif + break; + + case PRINT_QNX: + string_initial(&sDefault.szLpqcommand,"lpq -P%p"); + string_initial(&sDefault.szLprmcommand,"lprm -P%p %j"); + string_initial(&sDefault.szPrintcommand,"lp -r -P%p %s"); + break; + + + } +} + + +/******************************************************************* a +convenience routine to grab string parameters into a rotating buffer, +and run standard_sub_basic on them. The buffers can be written to by +callers without affecting the source string. +********************************************************************/ +char *lp_string(char *s) +{ + static char *bufs[10]; + static int buflen[10]; + static int next = -1; + char *ret; + int i; + int len = s?strlen(s):0; + + if (next == -1) { + /* initialisation */ + for (i=0;i<10;i++) { + bufs[i] = NULL; + buflen[i] = 0; + } + next = 0; + } + + len = MAX(len+100,sizeof(pstring)); /* the +100 is for some + substitution room */ + + if (buflen[next] != len) { + buflen[next] = len; + if (bufs[next]) free(bufs[next]); + bufs[next] = (char *)malloc(len); + if (!bufs[next]) { + DEBUG(0,("out of memory in lp_string()")); + exit(1); + } + } + + ret = &bufs[next][0]; + next = (next+1)%10; + + if (!s) + *ret = 0; + else + StrCpy(ret,s); + + standard_sub_basic(ret); + return(ret); +} + + +/* + In this section all the functions that are used to access the + parameters from the rest of the program are defined +*/ + +#define FN_GLOBAL_STRING(fn_name,ptr) \ + char *fn_name(void) {return(lp_string(*(char **)(ptr) ? *(char **)(ptr) : ""));} +#define FN_GLOBAL_BOOL(fn_name,ptr) \ + BOOL fn_name(void) {return(*(BOOL *)(ptr));} +#define FN_GLOBAL_CHAR(fn_name,ptr) \ + char fn_name(void) {return(*(char *)(ptr));} +#define FN_GLOBAL_INTEGER(fn_name,ptr) \ + int fn_name(void) {return(*(int *)(ptr));} + +#define FN_LOCAL_STRING(fn_name,val) \ + char *fn_name(int i) {return(lp_string((LP_SNUM_OK(i)&&pSERVICE(i)->val)?pSERVICE(i)->val : sDefault.val));} +#define FN_LOCAL_BOOL(fn_name,val) \ + BOOL fn_name(int i) {return(LP_SNUM_OK(i)? pSERVICE(i)->val : sDefault.val);} +#define FN_LOCAL_CHAR(fn_name,val) \ + char fn_name(int i) {return(LP_SNUM_OK(i)? pSERVICE(i)->val : sDefault.val);} +#define FN_LOCAL_INTEGER(fn_name,val) \ + int fn_name(int i) {return(LP_SNUM_OK(i)? pSERVICE(i)->val : sDefault.val);} + +FN_GLOBAL_STRING(lp_logfile,&Globals.szLogFile) +FN_GLOBAL_STRING(lp_smbrun,&Globals.szSmbrun) +FN_GLOBAL_STRING(lp_configfile,&Globals.szConfigFile) +FN_GLOBAL_STRING(lp_smb_passwd_file,&Globals.szSMBPasswdFile) +FN_GLOBAL_STRING(lp_serverstring,&Globals.szServerString) +FN_GLOBAL_STRING(lp_printcapname,&Globals.szPrintcapname) +FN_GLOBAL_STRING(lp_lockdir,&Globals.szLockDir) +FN_GLOBAL_STRING(lp_rootdir,&Globals.szRootdir) +FN_GLOBAL_STRING(lp_defaultservice,&Globals.szDefaultService) +FN_GLOBAL_STRING(lp_msg_command,&Globals.szMsgCommand) +FN_GLOBAL_STRING(lp_dfree_command,&Globals.szDfree) +FN_GLOBAL_STRING(lp_hosts_equiv,&Globals.szHostsEquiv) +FN_GLOBAL_STRING(lp_auto_services,&Globals.szAutoServices) +FN_GLOBAL_STRING(lp_passwd_program,&Globals.szPasswdProgram) +FN_GLOBAL_STRING(lp_passwd_chat,&Globals.szPasswdChat) +FN_GLOBAL_STRING(lp_passwordserver,&Globals.szPasswordServer) +FN_GLOBAL_STRING(lp_workgroup,&Globals.szWorkGroup) +FN_GLOBAL_STRING(lp_domain_controller,&Globals.szDomainController) +FN_GLOBAL_STRING(lp_username_map,&Globals.szUsernameMap) +FN_GLOBAL_STRING(lp_character_set,&Globals.szCharacterSet) +FN_GLOBAL_STRING(lp_logon_script,&Globals.szLogonScript) +FN_GLOBAL_STRING(lp_logon_path,&Globals.szLogonPath) +FN_GLOBAL_STRING(lp_veto_files,&Globals.szVetoFiles) +FN_GLOBAL_STRING(lp_remote_announce,&Globals.szRemoteAnnounce) +FN_GLOBAL_STRING(lp_wins_server,&Globals.szWINSserver) +FN_GLOBAL_STRING(lp_interfaces,&Globals.szInterfaces) +FN_GLOBAL_STRING(lp_socket_address,&Globals.szSocketAddress) +FN_GLOBAL_STRING(lp_nis_home_map_name,&Globals.szNISHomeMapName) + +FN_GLOBAL_BOOL(lp_wins_support,&Globals.bWINSsupport) +FN_GLOBAL_BOOL(lp_wins_proxy,&Globals.bWINSproxy) +FN_GLOBAL_BOOL(lp_local_master,&Globals.bLocalMaster) +FN_GLOBAL_BOOL(lp_domain_master,&Globals.bDomainMaster) +FN_GLOBAL_BOOL(lp_domain_logons,&Globals.bDomainLogons) +FN_GLOBAL_BOOL(lp_preferred_master,&Globals.bPreferredMaster) +FN_GLOBAL_BOOL(lp_load_printers,&Globals.bLoadPrinters) +FN_GLOBAL_BOOL(lp_use_rhosts,&Globals.bUseRhosts) +FN_GLOBAL_BOOL(lp_getwdcache,&use_getwd_cache) +FN_GLOBAL_BOOL(lp_readprediction,&Globals.bReadPrediction) +FN_GLOBAL_BOOL(lp_readbmpx,&Globals.bReadbmpx) +FN_GLOBAL_BOOL(lp_readraw,&Globals.bReadRaw) +FN_GLOBAL_BOOL(lp_writeraw,&Globals.bWriteRaw) +FN_GLOBAL_BOOL(lp_null_passwords,&Globals.bNullPasswords) +FN_GLOBAL_BOOL(lp_strip_dot,&Globals.bStripDot) +FN_GLOBAL_BOOL(lp_encrypted_passwords,&Globals.bEncryptPasswords) +FN_GLOBAL_BOOL(lp_syslog_only,&Globals.bSyslogOnly) +FN_GLOBAL_BOOL(lp_browse_list,&Globals.bBrowseList) +FN_GLOBAL_BOOL(lp_unix_realname,&Globals.bUnixRealname) +FN_GLOBAL_BOOL(lp_nis_home_map,&Globals.bNISHomeMap) + +FN_GLOBAL_INTEGER(lp_os_level,&Globals.os_level) +FN_GLOBAL_INTEGER(lp_max_ttl,&Globals.max_ttl) +FN_GLOBAL_INTEGER(lp_max_log_size,&Globals.max_log_size) +FN_GLOBAL_INTEGER(lp_mangledstack,&Globals.mangled_stack) +FN_GLOBAL_INTEGER(lp_maxxmit,&Globals.max_xmit) +FN_GLOBAL_INTEGER(lp_maxmux,&Globals.max_mux) +FN_GLOBAL_INTEGER(lp_maxpacket,&Globals.max_packet) +FN_GLOBAL_INTEGER(lp_keepalive,&keepalive) +FN_GLOBAL_INTEGER(lp_passwordlevel,&Globals.pwordlevel) +FN_GLOBAL_INTEGER(lp_readsize,&Globals.ReadSize) +FN_GLOBAL_INTEGER(lp_shmem_size,&Globals.shmem_size) +FN_GLOBAL_INTEGER(lp_shmem_hash_size,&Globals.shmem_hash_size) +FN_GLOBAL_INTEGER(lp_deadtime,&Globals.deadtime) +FN_GLOBAL_INTEGER(lp_maxprotocol,&Globals.maxprotocol) +FN_GLOBAL_INTEGER(lp_security,&Globals.security) +FN_GLOBAL_INTEGER(lp_printing,&Globals.printing) +FN_GLOBAL_INTEGER(lp_maxdisksize,&Globals.maxdisksize) +FN_GLOBAL_INTEGER(lp_lpqcachetime,&Globals.lpqcachetime) +FN_GLOBAL_INTEGER(lp_syslog,&Globals.syslog) + +FN_LOCAL_STRING(lp_preexec,szPreExec) +FN_LOCAL_STRING(lp_postexec,szPostExec) +FN_LOCAL_STRING(lp_rootpreexec,szRootPreExec) +FN_LOCAL_STRING(lp_rootpostexec,szRootPostExec) +FN_LOCAL_STRING(lp_servicename,szService) +FN_LOCAL_STRING(lp_pathname,szPath) +FN_LOCAL_STRING(lp_dontdescend,szDontdescend) +FN_LOCAL_STRING(lp_username,szUsername) +FN_LOCAL_STRING(lp_guestaccount,szGuestaccount) +FN_LOCAL_STRING(lp_invalid_users,szInvalidUsers) +FN_LOCAL_STRING(lp_valid_users,szValidUsers) +FN_LOCAL_STRING(lp_admin_users,szAdminUsers) +FN_LOCAL_STRING(lp_printcommand,szPrintcommand) +FN_LOCAL_STRING(lp_lpqcommand,szLpqcommand) +FN_LOCAL_STRING(lp_lprmcommand,szLprmcommand) +FN_LOCAL_STRING(lp_lppausecommand,szLppausecommand) +FN_LOCAL_STRING(lp_lpresumecommand,szLpresumecommand) +FN_LOCAL_STRING(lp_printername,szPrintername) +FN_LOCAL_STRING(lp_printerdriver,szPrinterDriver) +FN_LOCAL_STRING(lp_hostsallow,szHostsallow) +FN_LOCAL_STRING(lp_hostsdeny,szHostsdeny) +FN_LOCAL_STRING(lp_magicscript,szMagicScript) +FN_LOCAL_STRING(lp_magicoutput,szMagicOutput) +FN_LOCAL_STRING(lp_comment,comment) +FN_LOCAL_STRING(lp_force_user,force_user) +FN_LOCAL_STRING(lp_force_group,force_group) +FN_LOCAL_STRING(lp_readlist,readlist) +FN_LOCAL_STRING(lp_writelist,writelist) +FN_LOCAL_STRING(lp_volume,volume) +FN_LOCAL_STRING(lp_mangled_map,szMangledMap) + +FN_LOCAL_BOOL(lp_alternate_permissions,bAlternatePerm) +FN_LOCAL_BOOL(lp_revalidate,bRevalidate) +FN_LOCAL_BOOL(lp_casesensitive,bCaseSensitive) +FN_LOCAL_BOOL(lp_preservecase,bCasePreserve) +FN_LOCAL_BOOL(lp_shortpreservecase,bShortCasePreserve) +FN_LOCAL_BOOL(lp_casemangle,bCaseMangle) +FN_LOCAL_BOOL(lp_status,status) +FN_LOCAL_BOOL(lp_hide_dot_files,bHideDotFiles) +FN_LOCAL_BOOL(lp_browseable,bBrowseable) +FN_LOCAL_BOOL(lp_readonly,bRead_only) +FN_LOCAL_BOOL(lp_no_set_dir,bNo_set_dir) +FN_LOCAL_BOOL(lp_guest_ok,bGuest_ok) +FN_LOCAL_BOOL(lp_guest_only,bGuest_only) +FN_LOCAL_BOOL(lp_print_ok,bPrint_ok) +FN_LOCAL_BOOL(lp_postscript,bPostscript) +FN_LOCAL_BOOL(lp_map_hidden,bMap_hidden) +FN_LOCAL_BOOL(lp_map_archive,bMap_archive) +FN_LOCAL_BOOL(lp_locking,bLocking) +FN_LOCAL_BOOL(lp_strict_locking,bStrictLocking) +FN_LOCAL_BOOL(lp_share_modes,bShareModes) +FN_LOCAL_BOOL(lp_onlyuser,bOnlyUser) +FN_LOCAL_BOOL(lp_manglednames,bMangledNames) +FN_LOCAL_BOOL(lp_widelinks,bWidelinks) +FN_LOCAL_BOOL(lp_syncalways,bSyncAlways) +FN_LOCAL_BOOL(lp_map_system,bMap_system) +FN_LOCAL_BOOL(lp_delete_readonly,bDeleteReadonly) +FN_LOCAL_BOOL(lp_fake_oplocks,bFakeOplocks) + +FN_LOCAL_INTEGER(lp_create_mode,iCreate_mode) +FN_LOCAL_INTEGER(lp_dir_mode,iDir_mode) +FN_LOCAL_INTEGER(lp_max_connections,iMaxConnections) +FN_LOCAL_INTEGER(lp_defaultcase,iDefaultCase) +FN_LOCAL_INTEGER(lp_minprintspace,iMinPrintSpace) + +FN_LOCAL_CHAR(lp_magicchar,magic_char) + + + +/* local prototypes */ +static int strwicmp( char *psz1, char *psz2 ); +static int map_parameter( char *pszParmName); +static BOOL set_boolean( BOOL *pb, char *pszParmValue ); +static int getservicebyname(char *pszServiceName, service *pserviceDest); +static void copy_service( service *pserviceDest, + service *pserviceSource, + BOOL *pcopymapDest ); +static BOOL service_ok(int iService); +static BOOL do_parameter(char *pszParmName, char *pszParmValue); +static BOOL do_section(char *pszSectionName); +static void dump_globals(void); +static void dump_a_service(service *pService); +static void init_copymap(service *pservice); + + +/*************************************************************************** +initialise a service to the defaults +***************************************************************************/ +static void init_service(service *pservice) +{ + bzero((char *)pservice,sizeof(service)); + copy_service(pservice,&sDefault,NULL); +} + + +/*************************************************************************** +free the dynamically allocated parts of a service struct +***************************************************************************/ +static void free_service(service *pservice) +{ + int i; + if (!pservice) + return; + + for (i=0;parm_table[i].label;i++) + if ((parm_table[i].type == P_STRING || + parm_table[i].type == P_STRING) && + parm_table[i].class == P_LOCAL) + string_free((char **)(((char *)pservice) + PTR_DIFF(parm_table[i].ptr,&sDefault))); +} + +/*************************************************************************** +add a new service to the services array initialising it with the given +service +***************************************************************************/ +static int add_a_service(service *pservice, char *name) +{ + int i; + service tservice; + int num_to_alloc = iNumServices+1; + + tservice = *pservice; + + /* it might already exist */ + if (name) + { + i = getservicebyname(name,NULL); + if (i >= 0) + return(i); + } + + /* find an invalid one */ + for (i=0;i<iNumServices;i++) + if (!pSERVICE(i)->valid) + break; + + /* if not, then create one */ + if (i == iNumServices) + { + ServicePtrs = (service **)Realloc(ServicePtrs,sizeof(service *)*num_to_alloc); + if (ServicePtrs) + pSERVICE(iNumServices) = (service *)malloc(sizeof(service)); + + if (!ServicePtrs || !pSERVICE(iNumServices)) + return(-1); + + iNumServices++; + } + else + free_service(pSERVICE(i)); + + pSERVICE(i)->valid = True; + + init_service(pSERVICE(i)); + copy_service(pSERVICE(i),&tservice,NULL); + if (name) + string_set(&iSERVICE(i).szService,name); + + return(i); +} + +/*************************************************************************** +add a new home service, with the specified home directory, defaults coming +from service ifrom +***************************************************************************/ +BOOL lp_add_home(char *pszHomename, int iDefaultService, char *pszHomedir) +{ + int i = add_a_service(pSERVICE(iDefaultService),pszHomename); + + if (i < 0) + return(False); + + if (!(*(iSERVICE(i).szPath)) || strequal(iSERVICE(i).szPath,lp_pathname(-1))) + string_set(&iSERVICE(i).szPath,pszHomedir); + if (!(*(iSERVICE(i).comment))) + { + pstring comment; + sprintf(comment,"Home directory of %s",pszHomename); + string_set(&iSERVICE(i).comment,comment); + } + iSERVICE(i).bAvailable = sDefault.bAvailable; + iSERVICE(i).bBrowseable = sDefault.bBrowseable; + + DEBUG(3,("adding home directory %s at %s\n", pszHomename, pszHomedir)); + + return(True); +} + +/*************************************************************************** +add a new service, based on an old one +***************************************************************************/ +int lp_add_service(char *pszService, int iDefaultService) +{ + return(add_a_service(pSERVICE(iDefaultService),pszService)); +} + + +/*************************************************************************** +add the IPC service +***************************************************************************/ +static BOOL lp_add_ipc(void) +{ + pstring comment; + int i = add_a_service(&sDefault,"IPC$"); + + if (i < 0) + return(False); + + sprintf(comment,"IPC Service (%s)",lp_serverstring()); + + string_set(&iSERVICE(i).szPath,tmpdir()); + string_set(&iSERVICE(i).szUsername,""); + string_set(&iSERVICE(i).comment,comment); + iSERVICE(i).status = False; + iSERVICE(i).iMaxConnections = 0; + iSERVICE(i).bAvailable = True; + iSERVICE(i).bRead_only = True; + iSERVICE(i).bGuest_only = False; + iSERVICE(i).bGuest_ok = True; + iSERVICE(i).bPrint_ok = False; + iSERVICE(i).bBrowseable = sDefault.bBrowseable; + + DEBUG(3,("adding IPC service\n")); + + return(True); +} + + +/*************************************************************************** +add a new printer service, with defaults coming from service iFrom +***************************************************************************/ +BOOL lp_add_printer(char *pszPrintername, int iDefaultService) +{ + char *comment = "From Printcap"; + int i = add_a_service(pSERVICE(iDefaultService),pszPrintername); + + if (i < 0) + return(False); + + /* note that we do NOT default the availability flag to True - */ + /* we take it from the default service passed. This allows all */ + /* dynamic printers to be disabled by disabling the [printers] */ + /* entry (if/when the 'available' keyword is implemented!). */ + + /* the printer name is set to the service name. */ + string_set(&iSERVICE(i).szPrintername,pszPrintername); + string_set(&iSERVICE(i).comment,comment); + iSERVICE(i).bBrowseable = sDefault.bBrowseable; + /* Printers cannot be read_only. */ + iSERVICE(i).bRead_only = False; + /* No share modes on printer services. */ + iSERVICE(i).bShareModes = False; + + DEBUG(3,("adding printer service %s\n",pszPrintername)); + + return(True); +} + + +/*************************************************************************** +Do a case-insensitive, whitespace-ignoring string compare. +***************************************************************************/ +static int strwicmp(char *psz1, char *psz2) +{ + /* if BOTH strings are NULL, return TRUE, if ONE is NULL return */ + /* appropriate value. */ + if (psz1 == psz2) + return (0); + else + if (psz1 == NULL) + return (-1); + else + if (psz2 == NULL) + return (1); + + /* sync the strings on first non-whitespace */ + while (1) + { + while (isspace(*psz1)) + psz1++; + while (isspace(*psz2)) + psz2++; + if (toupper(*psz1) != toupper(*psz2) || *psz1 == '\0' || *psz2 == '\0') + break; + psz1++; + psz2++; + } + return (*psz1 - *psz2); +} + +/*************************************************************************** +Map a parameter's string representation to something we can use. +Returns False if the parameter string is not recognised, else TRUE. +***************************************************************************/ +static int map_parameter(char *pszParmName) +{ + int iIndex; + + if (*pszParmName == '-') + return(-1); + + for (iIndex = 0; parm_table[iIndex].label; iIndex++) + if (strwicmp(parm_table[iIndex].label, pszParmName) == 0) + return(iIndex); + + DEBUG(0,( "Unknown parameter encountered: \"%s\"\n", pszParmName)); + return(-1); +} + + +/*************************************************************************** +Set a boolean variable from the text value stored in the passed string. +Returns True in success, False if the passed string does not correctly +represent a boolean. +***************************************************************************/ +static BOOL set_boolean(BOOL *pb, char *pszParmValue) +{ + BOOL bRetval; + + bRetval = True; + if (strwicmp(pszParmValue, "yes") == 0 || + strwicmp(pszParmValue, "true") == 0 || + strwicmp(pszParmValue, "1") == 0) + *pb = True; + else + if (strwicmp(pszParmValue, "no") == 0 || + strwicmp(pszParmValue, "False") == 0 || + strwicmp(pszParmValue, "0") == 0) + *pb = False; + else + { + DEBUG(0,( "Badly formed boolean in configuration file: \"%s\".\n", + pszParmValue)); + bRetval = False; + } + return (bRetval); +} + +/*************************************************************************** +Find a service by name. Otherwise works like get_service. +***************************************************************************/ +static int getservicebyname(char *pszServiceName, service *pserviceDest) +{ + int iService; + + for (iService = iNumServices - 1; iService >= 0; iService--) + if (VALID(iService) && + strwicmp(iSERVICE(iService).szService, pszServiceName) == 0) + { + if (pserviceDest != NULL) + copy_service(pserviceDest, pSERVICE(iService), NULL); + break; + } + + return (iService); +} + + + +/*************************************************************************** +Copy a service structure to another + +If pcopymapDest is NULL then copy all fields +***************************************************************************/ +static void copy_service(service *pserviceDest, + service *pserviceSource, + BOOL *pcopymapDest) +{ + int i; + BOOL bcopyall = (pcopymapDest == NULL); + + for (i=0;parm_table[i].label;i++) + if (parm_table[i].ptr && parm_table[i].class == P_LOCAL && + (bcopyall || pcopymapDest[i])) + { + void *def_ptr = parm_table[i].ptr; + void *src_ptr = + ((char *)pserviceSource) + PTR_DIFF(def_ptr,&sDefault); + void *dest_ptr = + ((char *)pserviceDest) + PTR_DIFF(def_ptr,&sDefault); + + switch (parm_table[i].type) + { + case P_BOOL: + case P_BOOLREV: + *(BOOL *)dest_ptr = *(BOOL *)src_ptr; + break; + + case P_INTEGER: + case P_OCTAL: + *(int *)dest_ptr = *(int *)src_ptr; + break; + + case P_CHAR: + *(char *)dest_ptr = *(char *)src_ptr; + break; + + case P_STRING: + string_set(dest_ptr,*(char **)src_ptr); + break; + + case P_USTRING: + string_set(dest_ptr,*(char **)src_ptr); + strupper(*(char **)dest_ptr); + break; + default: + break; + } + } + + if (bcopyall) + { + init_copymap(pserviceDest); + if (pserviceSource->copymap) + memcpy((void *)pserviceDest->copymap, + (void *)pserviceSource->copymap,sizeof(BOOL)*NUMPARAMETERS); + } +} + +/*************************************************************************** +Check a service for consistency. Return False if the service is in any way +incomplete or faulty, else True. +***************************************************************************/ +static BOOL service_ok(int iService) +{ + BOOL bRetval; + + bRetval = True; + if (iSERVICE(iService).szService[0] == '\0') + { + DEBUG(0,( "The following message indicates an internal error:\n")); + DEBUG(0,( "No service name in service entry.\n")); + bRetval = False; + } + + /* The [printers] entry MUST be printable. I'm all for flexibility, but */ + /* I can't see why you'd want a non-printable printer service... */ + if (strwicmp(iSERVICE(iService).szService,PRINTERS_NAME) == 0) + if (!iSERVICE(iService).bPrint_ok) + { + DEBUG(0,( "WARNING: [%s] service MUST be printable!\n", + iSERVICE(iService).szService)); + iSERVICE(iService).bPrint_ok = True; + } + + if (iSERVICE(iService).szPath[0] == '\0' && + strwicmp(iSERVICE(iService).szService,HOMES_NAME) != 0) + { + DEBUG(0,("No path in service %s - using %s\n",iSERVICE(iService).szService,tmpdir())); + string_set(&iSERVICE(iService).szPath,tmpdir()); + } + + /* If a service is flagged unavailable, log the fact at level 0. */ + if (!iSERVICE(iService).bAvailable) + DEBUG(1,( "NOTE: Service %s is flagged unavailable.\n", + iSERVICE(iService).szService)); + + return (bRetval); +} + +static struct file_lists { + struct file_lists *next; + char *name; + time_t modtime; +} *file_lists = NULL; + +/******************************************************************* +keep a linked list of all config files so we know when one has changed +it's date and needs to be reloaded +********************************************************************/ +static void add_to_file_list(char *fname) +{ + struct file_lists *f=file_lists; + + while (f) { + if (f->name && !strcmp(f->name,fname)) break; + f = f->next; + } + + if (!f) { + f = (struct file_lists *)malloc(sizeof(file_lists[0])); + if (!f) return; + f->next = file_lists; + f->name = strdup(fname); + if (!f->name) { + free(f); + return; + } + file_lists = f; + } + + { + pstring n2; + strcpy(n2,fname); + standard_sub_basic(n2); + f->modtime = file_modtime(n2); + } + +} + +/******************************************************************* +check if a config file has changed date +********************************************************************/ +BOOL lp_file_list_changed(void) +{ + struct file_lists *f = file_lists; + while (f) { + pstring n2; + strcpy(n2,f->name); + standard_sub_basic(n2); + if (f->modtime != file_modtime(n2)) return(True); + f = f->next; + } + return(False); +} + +#ifdef KANJI +/*************************************************************************** + handle the interpretation of the coding system parameter + *************************************************************************/ +static BOOL handle_coding_system(char *pszParmValue,int *val) +{ + *val = interpret_coding_system(pszParmValue,*val); + return(True); +} +#endif /* KANJI */ + +/*************************************************************************** +handle the interpretation of the character set system parameter +***************************************************************************/ +static BOOL handle_character_set(char *pszParmValue,int *val) +{ + string_set(&Globals.szCharacterSet,pszParmValue); + *val = interpret_character_set(pszParmValue,*val); + return(True); +} + + +/*************************************************************************** +handle the interpretation of the protocol parameter +***************************************************************************/ +static BOOL handle_protocol(char *pszParmValue,int *val) +{ + *val = interpret_protocol(pszParmValue,*val); + return(True); +} + +/*************************************************************************** +handle the interpretation of the security parameter +***************************************************************************/ +static BOOL handle_security(char *pszParmValue,int *val) +{ + *val = interpret_security(pszParmValue,*val); + return(True); +} + +/*************************************************************************** +handle the interpretation of the default case +***************************************************************************/ +static BOOL handle_case(char *pszParmValue,int *val) +{ + if (strequal(pszParmValue,"LOWER")) + *val = CASE_LOWER; + else if (strequal(pszParmValue,"UPPER")) + *val = CASE_UPPER; + return(True); +} + +/*************************************************************************** +handle the interpretation of the printing system +***************************************************************************/ +static BOOL handle_printing(char *pszParmValue,int *val) +{ + if (strequal(pszParmValue,"sysv")) + *val = PRINT_SYSV; + else if (strequal(pszParmValue,"aix")) + *val = PRINT_AIX; + else if (strequal(pszParmValue,"hpux")) + *val = PRINT_HPUX; + else if (strequal(pszParmValue,"bsd")) + *val = PRINT_BSD; + else if (strequal(pszParmValue,"qnx")) + *val = PRINT_QNX; + else if (strequal(pszParmValue,"plp")) + *val = PRINT_PLP; + else if (strequal(pszParmValue,"lprng")) + *val = PRINT_LPRNG; + return(True); +} + +/*************************************************************************** +handle the valid chars lines +***************************************************************************/ +static BOOL handle_valid_chars(char *pszParmValue,char **ptr) +{ + string_set(ptr,pszParmValue); + + add_char_string(pszParmValue); + return(True); +} + + +/*************************************************************************** +handle the include operation +***************************************************************************/ +static BOOL handle_include(char *pszParmValue,char **ptr) +{ + pstring fname; + strcpy(fname,pszParmValue); + + add_to_file_list(fname); + + standard_sub_basic(fname); + + string_set(ptr,fname); + + if (file_exist(fname,NULL)) + return(pm_process(fname, do_section, do_parameter)); + + DEBUG(2,("Can't find include file %s\n",fname)); + + return(False); +} + + +/*************************************************************************** +handle the interpretation of the copy parameter +***************************************************************************/ +static BOOL handle_copy(char *pszParmValue,char **ptr) +{ + BOOL bRetval; + int iTemp; + service serviceTemp; + + string_set(ptr,pszParmValue); + + init_service(&serviceTemp); + + bRetval = False; + + DEBUG(3,("Copying service from service %s\n",pszParmValue)); + + if ((iTemp = getservicebyname(pszParmValue, &serviceTemp)) >= 0) + { + if (iTemp == iServiceIndex) + { + DEBUG(0,("Can't copy service %s - unable to copy self!\n", + pszParmValue)); + } + else + { + copy_service(pSERVICE(iServiceIndex), + &serviceTemp, + iSERVICE(iServiceIndex).copymap); + bRetval = True; + } + } + else + { + DEBUG(0,( "Unable to copy service - source not found: %s\n", + pszParmValue)); + bRetval = False; + } + + free_service(&serviceTemp); + return (bRetval); +} + + +/*************************************************************************** +initialise a copymap +***************************************************************************/ +static void init_copymap(service *pservice) +{ + int i; + if (pservice->copymap) free(pservice->copymap); + pservice->copymap = (BOOL *)malloc(sizeof(BOOL)*NUMPARAMETERS); + if (!pservice->copymap) + DEBUG(0,("Couldn't allocate copymap!! (size %d)\n",NUMPARAMETERS)); + + for (i=0;i<NUMPARAMETERS;i++) + pservice->copymap[i] = True; +} + + +/*************************************************************************** +Process a parameter. +***************************************************************************/ +static BOOL do_parameter(char *pszParmName, char *pszParmValue) +{ + int parmnum; + void *parm_ptr=NULL; /* where we are going to store the result */ + void *def_ptr=NULL; + + if (!bInGlobalSection && bGlobalOnly) return(True); + + DEBUG(3,("doing parameter %s = %s\n",pszParmName,pszParmValue)); + + parmnum = map_parameter(pszParmName); + + if (parmnum < 0) + { + DEBUG(0,( "Ignoring unknown parameter \"%s\"\n", pszParmName)); + return(True); + } + + def_ptr = parm_table[parmnum].ptr; + + /* we might point at a service, the default service or a global */ + if (bInGlobalSection) + parm_ptr = def_ptr; + else + { + if (parm_table[parmnum].class == P_GLOBAL) + { + DEBUG(0,( "Global parameter %s found in service section!\n",pszParmName)); + return(True); + } + parm_ptr = ((char *)pSERVICE(iServiceIndex)) + PTR_DIFF(def_ptr,&sDefault); + } + + if (!bInGlobalSection) + { + int i; + if (!iSERVICE(iServiceIndex).copymap) + init_copymap(pSERVICE(iServiceIndex)); + + /* this handles the aliases - set the copymap for other entries with + the same data pointer */ + for (i=0;parm_table[i].label;i++) + if (parm_table[i].ptr == parm_table[parmnum].ptr) + iSERVICE(iServiceIndex).copymap[i] = False; + } + + /* if it is a special case then go ahead */ + if (parm_table[parmnum].special) + { + parm_table[parmnum].special(pszParmValue,parm_ptr); + return(True); + } + + /* now switch on the type of variable it is */ + switch (parm_table[parmnum].type) + { + case P_BOOL: + set_boolean(parm_ptr,pszParmValue); + break; + + case P_BOOLREV: + set_boolean(parm_ptr,pszParmValue); + *(BOOL *)parm_ptr = ! *(BOOL *)parm_ptr; + break; + + case P_INTEGER: + *(int *)parm_ptr = atoi(pszParmValue); + break; + + case P_CHAR: + *(char *)parm_ptr = *pszParmValue; + break; + + case P_OCTAL: + sscanf(pszParmValue,"%o",(int *)parm_ptr); + break; + + case P_STRING: + string_set(parm_ptr,pszParmValue); + break; + + case P_USTRING: + string_set(parm_ptr,pszParmValue); + strupper(*(char **)parm_ptr); + break; + + case P_GSTRING: + strcpy((char *)parm_ptr,pszParmValue); + break; + + case P_UGSTRING: + strcpy((char *)parm_ptr,pszParmValue); + strupper((char *)parm_ptr); + break; + } + + return(True); +} + +/*************************************************************************** +print a parameter of the specified type +***************************************************************************/ +static void print_parameter(parm_type type,void *ptr) +{ + switch (type) + { + case P_BOOL: + printf("%s",BOOLSTR(*(BOOL *)ptr)); + break; + + case P_BOOLREV: + printf("%s",BOOLSTR(! *(BOOL *)ptr)); + break; + + case P_INTEGER: + printf("%d",*(int *)ptr); + break; + + case P_CHAR: + printf("%c",*(char *)ptr); + break; + + case P_OCTAL: + printf("0%o",*(int *)ptr); + break; + + case P_GSTRING: + case P_UGSTRING: + if ((char *)ptr) + printf("%s",(char *)ptr); + break; + + case P_STRING: + case P_USTRING: + if (*(char **)ptr) + printf("%s",*(char **)ptr); + break; + } +} + + +/*************************************************************************** +check if two parameters are equal +***************************************************************************/ +static BOOL equal_parameter(parm_type type,void *ptr1,void *ptr2) +{ + switch (type) + { + case P_BOOL: + case P_BOOLREV: + return(*((BOOL *)ptr1) == *((BOOL *)ptr2)); + + case P_INTEGER: + case P_OCTAL: + return(*((int *)ptr1) == *((int *)ptr2)); + + case P_CHAR: + return(*((char *)ptr1) == *((char *)ptr2)); + + case P_GSTRING: + case P_UGSTRING: + { + char *p1 = (char *)ptr1, *p2 = (char *)ptr2; + if (p1 && !*p1) p1 = NULL; + if (p2 && !*p2) p2 = NULL; + return(p1==p2 || strequal(p1,p2)); + } + case P_STRING: + case P_USTRING: + { + char *p1 = *(char **)ptr1, *p2 = *(char **)ptr2; + if (p1 && !*p1) p1 = NULL; + if (p2 && !*p2) p2 = NULL; + return(p1==p2 || strequal(p1,p2)); + } + } + return(False); +} + +/*************************************************************************** +Process a new section (service). At this stage all sections are services. +Later we'll have special sections that permit server parameters to be set. +Returns True on success, False on failure. +***************************************************************************/ +static BOOL do_section(char *pszSectionName) +{ + BOOL bRetval; + BOOL isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) || + (strwicmp(pszSectionName, GLOBAL_NAME2) == 0)); + bRetval = False; + + /* if we were in a global section then do the local inits */ + if (bInGlobalSection && !isglobal) + init_locals(); + + /* if we've just struck a global section, note the fact. */ + bInGlobalSection = isglobal; + + /* check for multiple global sections */ + if (bInGlobalSection) + { + DEBUG(3,( "Processing section \"[%s]\"\n", pszSectionName)); + return(True); + } + + if (!bInGlobalSection && bGlobalOnly) return(True); + + /* if we have a current service, tidy it up before moving on */ + bRetval = True; + + if (iServiceIndex >= 0) + bRetval = service_ok(iServiceIndex); + + /* if all is still well, move to the next record in the services array */ + if (bRetval) + { + /* We put this here to avoid an odd message order if messages are */ + /* issued by the post-processing of a previous section. */ + DEBUG(2,( "Processing section \"[%s]\"\n", pszSectionName)); + + if ((iServiceIndex=add_a_service(&sDefault,pszSectionName)) < 0) + { + DEBUG(0,("Failed to add a new service\n")); + return(False); + } + } + + return (bRetval); +} + +/*************************************************************************** +Display the contents of the global structure. +***************************************************************************/ +static void dump_globals(void) +{ + int i; + printf("Global parameters:\n"); + + for (i=0;parm_table[i].label;i++) + if (parm_table[i].class == P_GLOBAL && + parm_table[i].ptr && + (i == 0 || (parm_table[i].ptr != parm_table[i-1].ptr))) + { + printf("\t%s: ",parm_table[i].label); + print_parameter(parm_table[i].type,parm_table[i].ptr); + printf("\n"); + } +} + +/*************************************************************************** +Display the contents of a single services record. +***************************************************************************/ +static void dump_a_service(service *pService) +{ + int i; + if (pService == &sDefault) + printf("\nDefault service parameters:\n"); + else + printf("\nService parameters [%s]:\n",pService->szService); + + for (i=0;parm_table[i].label;i++) + if (parm_table[i].class == P_LOCAL && + parm_table[i].ptr && + (*parm_table[i].label != '-') && + (i == 0 || (parm_table[i].ptr != parm_table[i-1].ptr))) + { + int pdiff = PTR_DIFF(parm_table[i].ptr,&sDefault); + + if (pService == &sDefault || !equal_parameter(parm_table[i].type, + ((char *)pService) + pdiff, + ((char *)&sDefault) + pdiff)) + { + printf("\t%s: ",parm_table[i].label); + print_parameter(parm_table[i].type, + ((char *)pService) + pdiff); + printf("\n"); + } + } +} + +#if 0 +/*************************************************************************** +Display the contents of a single copy structure. +***************************************************************************/ +static void dump_copy_map(BOOL *pcopymap) +{ + int i; + if (!pcopymap) return; + + printf("\n\tNon-Copied parameters:\n"); + + for (i=0;parm_table[i].label;i++) + if (parm_table[i].class == P_LOCAL && + parm_table[i].ptr && !pcopymap[i] && + (i == 0 || (parm_table[i].ptr != parm_table[i-1].ptr))) + { + printf("\t\t%s\n",parm_table[i].label); + } +} +#endif + +/*************************************************************************** +Return TRUE if the passed service number is within range. +***************************************************************************/ +BOOL lp_snum_ok(int iService) +{ + return (LP_SNUM_OK(iService) && iSERVICE(iService).bAvailable); +} + + +/*************************************************************************** +auto-load some homes and printer services +***************************************************************************/ +static void lp_add_auto_services(char *str) +{ + char *s; + char *p; + int homes = lp_servicenumber(HOMES_NAME); + int printers = lp_servicenumber(PRINTERS_NAME); + + if (!str) + return; + + s = strdup(str); + if (!s) return; + + for (p=strtok(s,LIST_SEP);p;p=strtok(NULL,LIST_SEP)) + { + char *home = get_home_dir(p); + + if (lp_servicenumber(p) >= 0) continue; + + if (home && homes >= 0) + { + lp_add_home(p,homes,home); + continue; + } + + if (printers >= 0 && pcap_printername_ok(p,NULL)) + lp_add_printer(p,printers); + } + free(s); +} + +/*************************************************************************** +auto-load one printer +***************************************************************************/ +static void lp_add_one_printer(char *name,char *comment) +{ + int printers = lp_servicenumber(PRINTERS_NAME); + int i; + + if (lp_servicenumber(name) < 0) + { + lp_add_printer(name,printers); + if ((i=lp_servicenumber(name)) >= 0) + string_set(&iSERVICE(i).comment,comment); + } +} + + +/*************************************************************************** +auto-load printer services +***************************************************************************/ +static void lp_add_all_printers(void) +{ + int printers = lp_servicenumber(PRINTERS_NAME); + + if (printers < 0) return; + + pcap_printer_fn(lp_add_one_printer); +} + +/*************************************************************************** +have we loaded a services file yet? +***************************************************************************/ +BOOL lp_loaded(void) +{ + return(bLoaded); +} + +/*************************************************************************** +unload unused services +***************************************************************************/ +void lp_killunused(BOOL (*snumused)(int )) +{ + int i; + for (i=0;i<iNumServices;i++) + if (VALID(i) && !snumused(i)) + { + iSERVICE(i).valid = False; + free_service(pSERVICE(i)); + } +} + +/*************************************************************************** +Load the services array from the services file. Return True on success, +False on failure. +***************************************************************************/ +BOOL lp_load(char *pszFname,BOOL global_only) +{ + pstring n2; + BOOL bRetval; + + add_to_file_list(pszFname); + + bRetval = False; + + bInGlobalSection = True; + bGlobalOnly = global_only; + + init_globals(); + + strcpy(n2,pszFname); + standard_sub_basic(n2); + + /* We get sections first, so have to start 'behind' to make up */ + iServiceIndex = -1; + bRetval = pm_process(n2, do_section, do_parameter); + + /* finish up the last section */ + DEBUG(3,("pm_process() returned %s\n", BOOLSTR(bRetval))); + if (bRetval) + if (iServiceIndex >= 0) + bRetval = service_ok(iServiceIndex); + + lp_add_auto_services(lp_auto_services()); + if (lp_load_printers()) + lp_add_all_printers(); + + lp_add_ipc(); + + bLoaded = True; + + return (bRetval); +} + + +/*************************************************************************** +return the max number of services +***************************************************************************/ +int lp_numservices(void) +{ + return(iNumServices); +} + +/*************************************************************************** +Display the contents of the services array in human-readable form. +***************************************************************************/ +void lp_dump(void) +{ + int iService; + + dump_globals(); + + dump_a_service(&sDefault); + + for (iService = 0; iService < iNumServices; iService++) + { + if (VALID(iService)) + { + if (iSERVICE(iService).szService[0] == '\0') + break; + dump_a_service(pSERVICE(iService)); + } + } +} + +/*************************************************************************** +Return the number of the service with the given name, or -1 if it doesn't +exist. Note that this is a DIFFERENT ANIMAL from the internal function +getservicebyname()! This works ONLY if all services have been loaded, and +does not copy the found service. +***************************************************************************/ +int lp_servicenumber(char *pszServiceName) +{ + int iService; + + for (iService = iNumServices - 1; iService >= 0; iService--) + if (VALID(iService) && + strwicmp(iSERVICE(iService).szService, pszServiceName) == 0) + break; + + if (iService < 0) + DEBUG(7,("lp_servicenumber: couldn't find %s\n",pszServiceName)); + + return (iService); +} + +/******************************************************************* + a useful volume label function + ******************************************************************/ +char *volume_label(int snum) +{ + char *ret = lp_volume(snum); + if (!*ret) return(lp_servicename(snum)); + return(ret); +} diff --git a/source/param/params.c b/source/param/params.c new file mode 100644 index 00000000000..0fdde0348ff --- /dev/null +++ b/source/param/params.c @@ -0,0 +1,326 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + Parameter loading utlities + Copyright (C) Karl Auer 1993,1994,1997 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/************************************************************************** +PARAMS.C + +Copyright (C) 1990, 1991, 1992, 1993, 1994 Karl Auer + +This module provides for streamlines retrieval of information from a +Windows-like parameter files. There is a function which will search for +all sections in the file and call a specified function with each. There is +a similar function which will call a specified function for all parameters +in a section. The idea is that you pass the addresses of suitable functions +to a single function in this module which will then enumerate all sections, +and within each section all parameters, to your program. + +Parameter files contain text lines (newline delimited) which consist of +either a section name in square brackets or a parameter name, delimited +from the parameter value by an equals sign. Blank lines or lines where the +first non-whitespace character is a colon are ignored. All whitespace in +section names and parameter names is compressed to single spaces. Leading +and trailing whitespace on parameter names and parameter values is stripped. + +Only the first equals sign in a parameter line is significant - parameter +values may contain equals signs, square brackets and semicolons. Internal +whitespace is retained in parameter values. Parameter names may not start +with a square bracket, an equals sign or a semicolon, for obvious reasons. + +A sample parameter file might look like this: + +[things] +this=1 +that=2 +[other things] +the other = 3 + +**************************************************************************/ + +#include "includes.h" + +#include "smb.h" + +/* local variable pointing to passed filename */ +static char *pszParmFile = NULL; +extern int DEBUGLEVEL; + + +/************************************************************************** +Strip all leading whitespace from a string. +**************************************************************************/ +static void trimleft(char *psz) +{ + char *pszDest; + + pszDest = psz; + if (psz != NULL) + { + while (*psz != '\0' && isspace(*psz)) + psz++; + while (*psz != '\0') + *pszDest++ = *psz++; + *pszDest = '\0'; + } +} + +/************************************************************************** +Strip all trailing whitespace from a string. +**************************************************************************/ +static void trimright(char *psz) +{ + char *pszTemp; + + if (psz != NULL && psz[0] != '\0') + { + pszTemp = psz + strlen(psz) - 1; + while (isspace(*pszTemp)) + *pszTemp-- = '\0'; + } +} + +/*********************************************************************** +Collapse each whitespace area in a string to a single space. +***********************************************************************/ +static void collapse_spaces(char *psz) +{ + while (*psz) + if (isspace(*psz)) + { + *psz++ = ' '; + trimleft(psz); + } + else + psz++; +} + +/************************************************************************** +Return the value of the first non-white character in the specified string. +The terminating NUL counts as non-white for the purposes of this function. +Note - no check for a NULL string! What would we return? +**************************************************************************/ +static int firstnonwhite(char *psz) +{ + while (isspace(*psz) && (*psz != '\0')) + psz++; + return (*psz); +} + + +/************************************************************************** +Identifies all parameters in the current section, calls the parameter +function for each. Ignores comment lines, stops and backs up in file when +a section is encountered. Returns True on success, False on error. +**************************************************************************/ +static BOOL enumerate_parameters(FILE *fileIn, BOOL (*pfunc)(char *,char *)) +{ + pstring szBuf; + char *pszTemp; + BOOL bRetval; + long lFileOffset; + int cTemp; + BOOL bParmFound; + + bRetval = False; + bParmFound = False; + while (True) + { + /* first remember where we are */ + if ((lFileOffset = ftell(fileIn)) >= 0L) + { + /* then get and check a line */ + if (fgets_slash(szBuf, sizeof(szBuf)-1, fileIn) == NULL) + { + /* stop - return OK unless file error */ + bRetval = !ferror(fileIn); + if (!bRetval) + DEBUG(0,( "Read error on configuration file (enumerating parameters)!\n")); + break; + } + else + /* if first non-white is a '[', stop (new section) */ + if ((cTemp = firstnonwhite(szBuf)) == '[') + { + /* restore position to start of new section */ + if (fseek(fileIn, lFileOffset, SEEK_SET) < 0L) + { + DEBUG(0,( "Seek error on configuration file!\n")); + break; + } + + /* return success */ + bRetval = True; + break; + } + else + /* if it's a semicolon or line is blank, ignore the line */ + if (!cTemp || strchr(";#",cTemp)) + { + continue; + } + else + /* if no equals sign and line contains non-whitespace */ + /* then line is badly formed */ + if ((pszTemp = strchr(szBuf, '=')) == NULL) + { + DEBUG(0,( "Ignoring badly formed line: %s", szBuf)); + } + else + { + /* Note that we have found a parameter */ + bParmFound = True; + /* cut line at the equals sign */ + *pszTemp++ = '\0'; + /* trim leading and trailing space from both halves */ + trimright(szBuf); + trimleft(szBuf); + trimright(pszTemp); + trimleft(pszTemp); + /* process the parameter iff passed pointer not NULL */ + if (pfunc != NULL) + if (!pfunc(szBuf, pszTemp)) + break; + } + } + } + return (bRetval); +} + + +/*********************************************************************** +Close up s by n chars, at offset start. +***********************************************************************/ +static void closestr(char *s, int start, int n) +{ + char *src; + char *dest; + int len; + + if (n > 0) + if ((src = dest = s) != NULL) + { + len = strlen(s); + if (start >= 0 && start < len - n) + { + src += start + n; + dest += start; + + while (*src) + *dest++ = *src++; + *dest = '\0'; + } + } +} + +/************************************************************************** +Identifies all sections in the parameter file, calls passed section_func() +for each, passing the section name, then calls enumerate_parameters(). +Returns True on success, False on failure. Note that the section and +parameter names will have all internal whitespace areas collapsed to a +single space for processing. +**************************************************************************/ +static BOOL enumerate_sections(FILE *fileIn, + BOOL (*sfunc)(char *),BOOL (*pfunc)(char *,char *)) +{ + pstring szBuf; + BOOL bRetval; + BOOL bSectionFound; + + /* this makes sure we get include lines right */ + enumerate_parameters(fileIn, pfunc); + + bRetval = False; + bSectionFound = False; + while (True) + { + if (fgets_slash(szBuf, sizeof(szBuf)-1, fileIn) == NULL) + { + /* stop - return OK unless file error */ + bRetval = !ferror(fileIn); + if (!bRetval) + DEBUG(0,( "Read error on configuration file (enumerating sections)!\n")); + break; + } + else + { + trimleft(szBuf); + trimright(szBuf); + if (szBuf[0] == '[') + { + closestr(szBuf, 0, 1); + if (strlen(szBuf) > 1) + if (szBuf[strlen(szBuf) - 1] == ']') + { + /* found a section - note the fact */ + bSectionFound = True; + /* remove trailing metabracket */ + szBuf[strlen(szBuf) - 1] = '\0'; + /* remove leading and trailing whitespace from name */ + trimleft(szBuf); + trimright(szBuf); + /* reduce all internal whitespace to one space */ + collapse_spaces(szBuf); + /* process it - stop if the processing fails */ + if (sfunc != NULL) + if (!sfunc(szBuf)) + break; + if (!enumerate_parameters(fileIn, pfunc)) + break; + } + } + } + } + + return (bRetval); +} + +/************************************************************************** +Process the passed parameter file. + +Returns True if successful, else False. +**************************************************************************/ +BOOL pm_process(char *pszFileName,BOOL (*sfunc)(char *),BOOL (*pfunc)(char *,char *)) +{ + FILE *fileIn; + BOOL bRetval; + + bRetval = False; + + /* record the filename for use in error messages one day... */ + pszParmFile = pszFileName; + + if (pszParmFile == NULL || strlen(pszParmFile) < 1) + DEBUG(0,( "No configuration filename specified!\n")); + else + if ((fileIn = fopen(pszParmFile, "r")) == NULL) + DEBUG(0,( "Unable to open configuration file \"%s\"!\n", pszParmFile)); + else + { + DEBUG(3,("Processing configuration file \"%s\"\n", pszParmFile)); + bRetval = enumerate_sections(fileIn, sfunc, pfunc); + fclose(fileIn); + } + + if (!bRetval) + DEBUG(0,("pm_process retuned false\n")); + return (bRetval); +} + + |