Samba is an open source file server software that can be run on multiple platforms. If you use it, you will set it over its configuration file. If you want to write a code similar to reading such a configuration file, then below Samba extraction The code is very useful to you. It uses a callback mechanism to get configuration information. SMB.Conf is as follows # this is the main samba configuration file. You Should Read The # smb.conf (5) Manual Page in Order To Understand The Options listed # here. Samba Has a huge number of configurable options (Perhaps TOO # MANY!) MOST OF WHICH Aren't shown in this example ## any line Which starts with a; (semi-color) or a # (hash) # Is a comment and is ignored. in this example we will use a ## for commentry and a; for parts of the config file That You # May wish to enable ## NOTE: WHENEVER You Modify this file you shop run the commit "testparm "# to check this you have not master any barasi syntactic errors. ## ===================================== ============================ [global]
# Workgroup = NT-DOMAIN-NAME or Workgroup-name Workgroup = GDCATTSOFT
# Server string is the equivalent of the nt description field server string = Samba Server
# This option is important for security. It allows you to restrict # connections to machines which are on your local network. The # following example restricts access to two C class networks and # the "loopback" interface. For more examples of the syntax see # The smb.conf man page; hosts allow = 192.168.1. 192.168.2. 127.
# If you want to automatically load your printer list rather # than setting them up individually then you'll need this printcap name = / etc / printcap load printers = yes # It should not be necessary to spell out the print system type unless # yours Is Non-Standard. Currently Supported Print Systems include: # BSD, SYSV, PLP, Lprng, AIX, HPUX, QNX, CUPS Printing = Cups
# Uncomment, you must add this to / etc / passwd # Otherwise the user "nobody" is buy; guest account = pcguest
# this tells samba to use a separate log file for each machine # That connection log file = /var/log/samba/%m.log
# Put a capping on the size of the log file (in kb). Max log size = 0
# Security mode. MOST People Want User Level Security. See # security_level.txt for details.
# Use password server option only with security = server # The argument list may include: # password server = My_PDC_Name [My_BDC_Name] [My_Next_BDC_Name] # or to auto-locate the domain controller / s # password server = *; password server =
# Password Level Allows matching of _n_ characters of the password for # all combinations of upper and limited .; password level = 8; username level = 8
# You may wish to use password encryption. Please read # ENCRYPTION.txt, Win95.txt and WinNT.txt in the Samba documentation. # Do not enable this option unless you have read those documents encrypt passwords = yes smb passwd file = / etc / samba / smbpasswd
# T FOLLOWING IS NEEDED TO Keep Smbclient from Spouting Spurious Errors # When Samba Is Built with Support for Ssl .; SSL CA CA CERTFILE = /usR/share/ssl/certs/ca-bundle.crt ..... / * -------------------------------------------------- ---------------------- ** * * Module Name: params * * ------------------ -------------------------------------------------- ------ ** * * This Module Performs Lexical Analysis and INITIAL PARSING OF A * Windows-like Parameter File. It Recognizes and Handles Four Token * Types: Section-Name, Parameter-Name, Parameter-Value, And * end-of-file. Comments and line continuation are handled * internally. * * The entry point to the module is function pm_process (). This * function opens the source file, calls the Parse () function to parse * the input, and THEN Closes The File When Either The EOF Is Reached * OR A Fatal Error Is Encountered. * * A Sample Parameter File Might Look Like this: * * [Section One] * Parameter One = Value String * Parameter T wo = another value * [section two] * new parameter = some value or t'other * * The parameter file is divided into sections by section headers:. * section names enclosed in square brackets (. eg [section one]) * Each Section Contains Parameter Lines, Each of Which Consist of A * Parameter Name and Value Delimited by An equer sign. Roughly, The * syntax is: * *
* * Blank lines and comment lines are ignored Comment lines are lines * beginning with either a semicolon. ( ';'). Or a pound sign ( '#') * * All whitespace in section names and parameter names is compressed * to single spaces. Leading and trailing whitespace is stipped from * both names and values. * * 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 , * with the exception of the '/ r' character, which is stripped for * historic reasons. Parameter names may not start with a left square * bracket, an equal sign, a pound sign, or a semicolon, because these * are used To Identify other tokens. * ------------------------------------------- ------------------------------ ** * / # include "stdafx.h" #include
#ifdef win32 # include
#ifndef win32 # include
/ * ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------- ** * Define & Constants ... * /
#define bufr_inc 1024
#define false (0) #define true (1) #define auto (2)
#ifndef _booltypedef int bag; #define _bool / * so we don't typef Bool again in vfs.h * / # ENDIF
/ * free memory if the pointer is valid and zero the pointer * / # iFNDef Safe_Free # define saffe_free (x) DO {IF ((x)! = null) {free ((x)); (x) = NULL;} } while (0) #ENDIF
. / * Global val set if multibyte codepage * / extern int global_is_multibyte_codepage; extern int (* _skip_multibyte_char) (char c); # define skip_multibyte_char (c) ((* _skip_multibyte_char) ((c))) // # define get_character_len (x (GLOBAL_IS_MULTIBYTE_CODEPAGE? SKIP_MULTIBYTE_CHAR ((x)): 0) #define get_character_len (x) 0 / * ---------------------------- --------------------------------------------- ** * Variables ... * * DEBUGLEVEL -. The ubiquitous DEBUGLEVEL This determines which // DEBUG () * messages will be produced * bufr -. pointer to a global buffer This is probably a kludge, * but it was the nicest kludge I could think. Of (for now). * Bsize - The size of the global buffer
Static char * bufr = null; static int bsize = 0;
/ * We can't use file * due to the 256 fd limited - Use this cheap Hack instead * / typedef struct {charf; char * p; size_t size;} myfile;
Static int mygetc (myfile * f) {if (f-> p> = f-> buf f-> size) Return EOF; / * Be Sure to return chars> 127 as posital value * / return (int) (* (f-> p ) & 0x00FF);
Static void myfile_close (myfile * f) {if (! f) return; safe_free (f-> buf); Safe_Free (f);}
/ * ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------- ** * functions ... * /
Static int EatWhitespace (MyFile * Infile) / * -------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------- ** * Scan Past Whitespace (see ctype (3c)) And Return THE FIRST NON -whitespace * character, or newline, or EOF * * Input:... InFile - Input source * * Output: The next non-whitespace character in the input stream * * Notes: Because the config files use a line-oriented grammar, We * ExpliCitly Exclude the newline character from the list of * whitespace characters. * - Note That Both EOF (-1) and the Nul Character ('/ 0') Are * considered end-file markers. * * --- -------------------------------------------------- ------------------- ** * / {INT C; for (c = mygetc (infile); Isspace (c) && ('/ n'! = C) ; c = mygetc (infile)); return (c);} / * EatWhitespace * /
Static int equesum / * ------------------------------------------------------------------------------------------------------------------------------------------------------------ -------------------------------- ** * scan to the end of a comment. * * Input: Infile - INPUT Source. * * Output: The Character That Marks The End of the Comment. Normal, * this will be a newline, but it * might * be an eof. * * Notes: Because the config files Use a line-Oriented Grammar, WE * EXPLICITLY Exclude the newline character from the list of * whitespace characters. * - Note That Both EOF (-1) and the Nul Character ('/ 0') Are * considered end-file markers. * * ---- -------------------------------------------------- ------------------ ** * / {INT C;
For (c = mygetc (infile); ('/ n'! = c) && (EOF! = c) && (c> 0); c = mygetc (infile)); return (c);} / * Eatcomment * // ******************************************************** ************************************************* * SCAN BACKARDS WITHIN A STRING to Discover if the last non-white * character is a line-continalion Character ('//'). * * Input: line - a Pointer to a buffer containing the string to be * scanned. * POS - this is taken to be the offset of the end of the * string. this position is * not * scanned. * * Output: The offset of the '//' Character if it is found, or -1 to * indeicate That is not. * * ***************** *********************************************************** ********** /
Static int continuation (char * line, int pos) {int POS2 = 0;
POS -; WHILE ((POS> = 0) && Isspace ((int) line [pOS])) POS
/ * We Should Recognize IF `/` is part of a multibyte character or not. * / while (POS2 <= POS) {size_t skip = 0; Skip = GET_CHARACTER_LEN (Line [POS2]); if (SKIP) {POS2 = Skip;} else if (POS == POS2) {RETURN ((POS> = 0) && ('//' == line [pOS]))? POS: -1);} else {POS2 ;}} Return (-1);
Void * Realloc (void * p, size_t size) / * ------------------------------------- ----------------------------------- ** * Expand a Pointer to Be a particular size / * -------------------------------------------------- ------------------- ** / {void * Ret = null;
IF (size == 0) {IF (p) free (p); // debug (5, "" Realloc asked for 0 bytes / n ")); Return NULL;}
IF (! p) Ret = (void *) malloc (size); else ret = (void *) Realloc (p, size);
IF (! RET) Printf ("Memory Allocation Error: Failed to Expand TO% D Bytes / N", (int) size);
Return (RET);
Static Bool Section (MyFile * Infile, Bool (* sfunc) (Char *)) / * ------------------------------ ------------------------------------------ ** SCAN A Section Name, and pass the name to function sfunc () * * Input:... InFile - Input source * sfunc - Pointer to the function to be called if the section * name is successfully read * * Output: True if the section name was read and True Was Returned from *
i = 0; / * is the offset of the next free byte in bufr [] and * / end = 0; / *
C = EatWhitespace (Infile); / * We've Already Got The '['. scan * / / / * Past Initial White Space. * /
While ((EOF! = C) && (c> 0)) {
/ * Check what the buffer is big enough for the next character. * / If (i> (BSIZE - 2)) {char * TB;
TB = (char *) Realloc (bufr, bsize bufr_inc); if (null == TB) {// debug (0, ("% s Memory Re-Allocation Failure.", FUNC); Return (false); } Bufr = TB; BSize = bufr_inc;} / * handle a single character. * / Switch (c) {case ']': / * Found the closing bracket. * / Bufr [end] = '/ 0'; if (0 == End) / * DON't Allow An Empty Name. * / {// debug (0, ("% s Empty Section Name In Configuration File./N", FUNC)); Return (false);} // if (! sfunc (unix_to_dos (bufr))) / * got a valid name. DEAL with it. * / if (! sfunc (bufr)) / * got a valid name. deal with it. * / return (false ); (Void) Eatcomment (Infile); / * finish off the line. * / Return (true);
Case '/ n': / * got newline before closing ']'. * / i = continalion (bufr, i); / * Check for line continuation. * / if (i <0) {bufr [end] = '/ 0 '; // debug (0, ("% s badly formed line in configuration file:% s / n", func, bufr); return (false);} end = ((i> 0) && (' ' == BUFR [I - 1]))))? (i - 1): (i); c = mygetc (infile); / * Continue with next line. * / Break;
Default: / * All else area. * / if (iSSpace (c)) / * one space per whitespace region. * / {bufr [end] = ''; i = end 1; c = EatWhitespace Infile);} else / * all Others Copy Verbatim. * / {BUFR [i ] = C; end = i; c = mygetc (infile);}}} / * We arrive here if we've met the eof before the Closing Bracket. * / // debug (0, ("% s Unexpected Eof in The Configuration File:% S / N", FUNC, BUFR); Return (false);} / * section * /
Static Bool Parameter (MyFile * Infile, Bool (* pfunc) (Char *, Char *), INT C) / * ---------------------------------------------------------------------------------------------------------------------- ------------------------------------------------ ** * Scan a parameter name and value, and pass these two fields to pfunc () * * Input:.. InFile - The input source * pfunc - A pointer to the function that will be called to * process the parameter, once it has been scanned * c -. The first character of the parameter name, which * would have been read by Parse () Unlike a comment * line or a section header, there is no lead-in * character that can be discarded * * Output.. : True if the parameter name and value were scanned and processed * successfully, else False * * Notes:... This function is in two parts The first loop scans the * parameter name Internal whitespace is compressed, and an * equal sign (= Terminates TH e token. Leading and trailing * whitespace is discarded. The second loop scans the parameter * value. When both have been successfully identified, they are * passed to pfunc () for processing. * * ---------- -------------------------------------------------- ------------ ** * / {INT i = 0; / * position within bufr. * / Int end = 0; / * bufr [end] is current end-of-string. * / Int vStart = 0; / * Starting position of the parameter value. * / Char * func = "params.c: parameter () -"; / * read the parameter name. * / While (0 == vStart) / * Loop untric we've found the start of the value. * / {
IF (I> (BSIZE - 2)) / * EnSure there's space for next char. * / {char * TB; TB = (char *) Realloc (bufr, bsize bufr_inc); if (null == tb) {/ / Debug (0, ("% s Memory Re-Allocation Failure.", FUNC); Return (false);} bufr = TB; BSize = bufr_inc;} switch (c) {case '=': / * Equal Sign Marks end of parame. * / if (0 == end) / * DON '{// debug (0, ("% s invalid parameter name in config. file./n" , FUNC); RETURN (FALSE);} bufr [end ] = '/ 0'; / * mark end of string & advance. * / i = end; / * new string starts here. * / vStart = End; / * New string is parameter value. * / Bufr [i] = '/ 0'; / * new string is nul, for now. * / Break;
Case '/ N': / * Find Continuation Char, Else Error. * / i = Continuation (BUFR, I); IF (i <0) {bufr [end] = '/ 0'; // debug (1, "% s ignoring badly formed line in configuration file:% s / n", func, bufr)); return (TRUE);} END = ((i> 0) && ('== bufr [i - 1]) )? (i - 1): (i); c = mygetc (infile); / * read paste eoln. * / Break;
Case '/ 0': / * Shouldn't Have EOF WITHIN PARAM Name. * / Case EOF: BUFR [I] = '/ 0'; // Debug (1, ("% S Unexpected end-of-file at: % S / N ", FUNC, BUFR); RETURN (TRUE); Default: IF (Isspace (C)) / * One '' 'Per Whitespace Region. * / {BUFR [END] =' '; i = End 1; C = EatWhitespace (Infile);} else / * all tase verbatim. * / {Bufr [i ] = C; END = i; c = mygetc (infile);}}}
/ * Now parse the value. * / C = eatwhitespace (infile); / * again, trim listed white ((EOF! = C) && (c> 0)) {
IF (I> (BSIZE - 2)) / * make sure's enough room. * / {bsize = bufr_inc; bufr = (char *) Realloc (bufr, bsuze); if (null == bufr) {// debug (0, ("% s Memory Re-Allocation Failure.", FUNC)); Return (false);}}
Switch (c) {case '/ r': / * explicitly remove '/ r' Because the Older * / c = mygetc (infile); / * Version called fgets_slash () Which also * / break; / * removes them. * /
Case '/ N': / * Marks End of Value UnsS a '/'. * / i = continalion (bufr, i); if (i <0) c = 0; ELSE {for (end = i; " > = 0) && Isspace ((int) bufr [end]); end -); c = mygetc (infile);} Break;
Default: / * All Others Verbatim. Note That Spaces DO * / BUFR [i ] = C; / * NOT Advance
Return (PFUNC (BUFR, & BUFR [VStart]); / * Pass name & value to pfunc (). * /} / * parameter * /
Static Bool Parse (MyFile * Infile, Bool (* sfunc) (Char *), Bool (* Pfunc) (Char *, Char *)) / * ----------------- -------------------------------------------------- ----- ** * SCAN & PARSE THE INPUT. * * INPUT: INFILE - INPUT SOURCE. * Sfunc - Function To Be Called When a section (). * Pfunc - Function to Be Called When a parameter is scanned. * See parameter (). * * Output: True if the file was successful. * * Notes: The Input Can Be Viewed in Terms of 'Lines'. There Are Four * Types of Lines : * Blank - May Contain Whitespace, OtherWise Empty. * Comment - First Non-Whitespace Character Is A ';' or '#'. * The remain of the line is ignored. * Section - First Non-Whitespace Character Is A '[ '. * Parameter - The Defau LT Case. * * --------------------------------------------- --------------------------- ** * / {INT C;
C = EatWhitespace (Infile); WHILE ((EOF! = C) && (c> 0)) {switch (c) {case '/ n': / * blank line. * / c = eatwhitespace (Infile); Break; Case ';': / * comment line. * / case '#': c = Eatcomment (Infile); Break;
Case '[': / * section header. * / if (! section (infile, sfunc)) return (false); c = eatwhitespace (infile); BREAK
Case '//': / * bogus backslash. * / c = EatWhitespace (Infile); Break;
Default: / * parameter line. * / if (! Parameter (Infile, PFUNC, C)) Return (false); c = EatWhitespace (Infile); Break;}} return (TRUE);} / * parse * /
/ ************************************************** ********************************** LOAD A File Into Memory from A fd. ************* *********************************************************** ************ /
Char * fd_load (int fd, size_t * size) {struct stat sbuf; char * p;
IF (FSTAT (FD, & SBUF)! = 0) Return NULL;
P = (char *) malloc (SBUF.ST_SIZE 1); if (! p) return null; if (READ (FD, P, SBUF.ST_SIZE)! = SBUF.ST_SIZE) {SAFE_FREE (P); return null; } P [SBUF.ST_SIZE] = 0;
IF (size) * size = sbuf.st_size;
Return P;
/ ************************************************** *********************************************************** *********************************************************** ******** / CHAR * file_load (char * fname, size_t * size) {Int fd; char * p;
IF (! fname ||! * fname) Return NULL;
FD = Open (fname, o_rdonly); if (fd == -1) Return NULL; P = fd_load (fd, size);
Close (FD);
Return P;
Static myfile * openconffile (char * filename) / * ------------------------------------- --------------------------------- ** * Open a configuration file. * * Input: filename - the pathname of The config file to be opened. * * Output: a Pointer of Type (char **) to the line of the file * * ---------------------- -------------------------------------------------- ** * / {char * func = "params.c: OpenConfile () -"; // extern bool = in_client; // int LVL = IN_CLIENT? 1: 0; MyFile * Ret;
RET = (MyFile *) Malloc (SIZEOF (* RET)); if (! RET) Return NULL;
RET-> BUF = file_load (filename, & ret-> size); if (null == RET-> buf) {// debug ("% s unable to open configuration file /"% s / ": / N / T% S / N ", // Func, FileName, STRERROR (Errno))); SAFE_FREE (RET); return null;}
RET-> P = RET-> BUF; return (re);} / * openconffile * /
Bool PM_Process (Char * FileName, Bool (* sfunc) (Char *), Bool (* Pfunc) (Char *, Char *)) / * ------------------ -------------------------------------------------- ---- ** * Process the name. * * Input: filename - The pathname of the parameter file to be opened. * Sfunc - a Pointer to a function tria Will be called when * a section name is discovered. * Pfunc - a Pointer to a function That Will Be Called WHEN * A Parameter Name and Value Are Discovered. * * Output: True If The File Was Success, Parsed, Else False. * * ------------ -------------------------------------------------- ---------- ** * / {int result; myfile * infile; char * func = "params.c: pm_process () -"; infile = OpenConfile (filename); / * Open the config file * / If (null == infile) Return (false);
// debug (3, ("% s processing configuration file /"% s / "/ n", func, filename));
IF (NULL! = BUFR) / * if We Already Have A Buffer * / Result = PARS (Infile, Sfunc, PFUNC); / * (Recursive Call), Then Just * / / * USE IT. * /
Else / * if we don't have a buffer * / {/ * allocate one, kiln, * / bsize = bufr_inc; / * thrEn free. * / bufr = (char *) malloc (bsize); if (null = = BUFR) {// debug (0, ("% s Memory Allocation Failure./N", FUNC)); MyFile_Close (Infile); Return (false);} Result = PARSE (Infile, Sfunc, PFUNC); SAFE_FREE BUFR); bufr = NULL; bsize = 0;} myfile_close (infile);
if (! result) / * generic failure. * / {// debug (0, ("% s failed. Error Returned from params.c: paraSe () ./ n", func); return (false);}
Return (True); / * generic success. * /} / * pm_process * /
/ * ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------- /