home *** CD-ROM | disk | FTP | other *** search
/ Big Green CD 8 / BGCD_8_Dev.iso / NEXTSTEP / Networking / SambaManager / samba-1.9.17p4 / source / params.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-03-30  |  14.4 KB  |  466 lines

  1. /* 
  2.    Unix SMB/Netbios implementation.
  3.    Version 1.9.
  4.    Parameter loading utlities
  5.    Copyright (C) Karl Auer 1993,1994,1997
  6.    
  7.    This program is free software; you can redistribute it and/or modify
  8.    it under the terms of the GNU General Public License as published by
  9.    the Free Software Foundation; either version 2 of the License, or
  10.    (at your option) any later version.
  11.    
  12.    This program is distributed in the hope that it will be useful,
  13.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.    GNU General Public License for more details.
  16.    
  17.    You should have received a copy of the GNU General Public License
  18.    along with this program; if not, write to the Free Software
  19.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20. */
  21.  
  22. /**************************************************************************
  23. PARAMS.C
  24.  
  25. Copyright (C) 1990, 1991, 1992, 1993, 1994 Karl Auer
  26.  
  27. This module provides for streamlines retrieval of information from a
  28. Windows-like parameter files. There is a function which will search for
  29. all sections in the file and call a specified function with each. There is
  30. a similar function which will call a specified function for all parameters 
  31. in a section. The idea is that you pass the addresses of suitable functions
  32. to a single function in this module which will then enumerate all sections, 
  33. and within each section all parameters, to your program. 
  34.  
  35. Parameter files contain text lines (newline delimited) which consist of
  36. either a section name in square brackets or a parameter name, delimited
  37. from the parameter value by an equals sign. Blank lines or lines where the
  38. first non-whitespace character is a colon are ignored. All whitespace in
  39. section names and parameter names is compressed to single spaces. Leading 
  40. and trailing whitespace on parameter names and parameter values is stripped.
  41.  
  42. Only the first equals sign in a parameter line is significant - parameter
  43. values may contain equals signs, square brackets and semicolons. Internal
  44. whitespace is retained in parameter values. Parameter names may not start 
  45. with a square bracket, an equals sign or a semicolon, for obvious reasons. 
  46.  
  47. A sample parameter file might look like this:
  48.  
  49. [things]
  50. this=1
  51. that=2
  52. [other things]
  53. the other = 3
  54.  
  55. **************************************************************************/
  56.  
  57. #include "includes.h"
  58.  
  59. #include "smb.h"
  60.  
  61. /* local variable pointing to passed filename */
  62. static char *pszParmFile = NULL;
  63. extern int DEBUGLEVEL;
  64.  
  65. #ifdef USE_NETINFO
  66. typedef struct ENTRIES {
  67.       ni_id    dir;
  68.         void    *handle;
  69.     } ni_entries; 
  70.  
  71.  
  72. /**************************************************************************
  73. Identifies all parameters in the current section, calls the parameter
  74. function for each. Have to concatenate multiple values to one string.
  75. If no property `_<prop name>' is available, use the default separator (S_SEPARATOR)
  76. **************************************************************************/
  77. static BOOL ni_enumerate_parameters(void *handle, u_long id, BOOL (*pfunc)(char *,char *))
  78. {
  79.   ni_status        status;
  80.     ni_id                dir;
  81.     ni_proplist    props;
  82.     
  83.     int                    i, j;
  84.     pstring            buffer;
  85.     char                *separator;
  86.   BOOL                bRetval = False;
  87.     
  88.     dir.nii_object = id;
  89.   status = ni_read(handle, &dir, &props);
  90.  
  91.   if (status == NI_OK) {
  92.         for (i = 0; i < props.ni_proplist_len; i++) 
  93.             if (strcmp(props.ni_proplist_val[i].nip_name, S_SERVICENAME) && 
  94.                     (*props.ni_proplist_val[i].nip_name != '_')) {
  95.                 if (props.ni_proplist_val[i].nip_val.ni_namelist_len) {
  96.                     (void)strcpy(buffer, props.ni_proplist_val[i].nip_val.ni_namelist_val[0]);
  97.                     if (props.ni_proplist_val[i].nip_val.ni_namelist_len > 1) {
  98.                         /* Check if we have a `_<prop name>' parameter, of so, copy it's serparator character */
  99.                         if ((*props.ni_proplist_val[i+1].nip_name == '_') &&
  100.                                 !strcmp(props.ni_proplist_val[i+1].nip_name+1, props.ni_proplist_val[i].nip_name)) {
  101.                             separator = props.ni_proplist_val[i+1].nip_val.ni_namelist_val[0];
  102.                         } else
  103.                             separator = S_SEPARATOR;
  104.                         for (j = 1; j < props.ni_proplist_val[i].nip_val.ni_namelist_len; j++) {
  105.                             (void)strcat(buffer, separator);
  106.                             (void)strcat(buffer, props.ni_proplist_val[i].nip_val.ni_namelist_val[j]);
  107.                         }
  108.                     }
  109.                     pfunc(props.ni_proplist_val[i].nip_name, buffer);
  110.                 } else
  111.                     pfunc(props.ni_proplist_val[i].nip_name, "");
  112.                 bRetval = True;
  113.             }
  114.         ni_proplist_free(&props);
  115.     }
  116.                 
  117.     return bRetval;
  118. }
  119.  
  120.  
  121. /**************************************************************************
  122. Identifies all sections in the directory passed, calls passed section_func()
  123. for each, passing the section name, then calls ni_enumerate_parameters(). 
  124. Returns True on success, False on failure..
  125. **************************************************************************/
  126. static BOOL ni_enumerate_sections(ni_entries *level,
  127.                    BOOL (*sfunc)(char *),BOOL (*pfunc)(char *,char *))
  128. {
  129.   ni_status            status;
  130.     ni_entrylist    dirs;
  131.  
  132.     int                    i;
  133.   BOOL                bRetval = False;
  134.  
  135.     /*
  136.      * The subdirectories are the services we want to process.
  137.      * The contents of the subdirectories are the parameters.
  138.      */
  139.     status = ni_list(level->handle, &(level->dir), S_SERVICENAME, &dirs);
  140.     
  141.     if (status == NI_OK) {
  142.         for (i = 0; i < dirs.ni_entrylist_len; i++) 
  143.             if (dirs.ni_entrylist_val[i].names && dirs.ni_entrylist_val[i].names[0].ni_namelist_len)
  144.                     if (sfunc(dirs.ni_entrylist_val[i].names[0].ni_namelist_val[0]))
  145.                         bRetval|= ni_enumerate_parameters(level->handle, dirs.ni_entrylist_val[i].id, pfunc);
  146.         
  147.         ni_entrylist_free(&dirs);
  148.     }
  149.     
  150.     return bRetval;
  151. }
  152.  
  153.  
  154. /**************************************************************************
  155. Process the passed parameter file.
  156.  
  157. Returns True if successful, else False.
  158. **************************************************************************/
  159. BOOL pm_process(char *pszFileName,BOOL (*sfunc)(char *),BOOL (*pfunc)(char *,char *))
  160. {
  161.     ni_status                        status;
  162.     struct sockaddr_in    addr;
  163.     ni_name                            tag;
  164.     
  165.   BOOL                bRetval = False;
  166.     int                    i, levels = 0;
  167.     
  168.     ni_entries list[100]; /* Will we ever have more than 100 levels? */
  169.     
  170.     /*
  171.      * Scan the NetInfo hierarchy, starting from the local level,
  172.      * until either an entry is found or we are past the top level.
  173.      * Then process the entries found in reverse order.
  174.      */
  175.  
  176.     DEBUG(3,("Checking netinfo for directory %s ...", S_SAMBADIR));
  177.     list[levels].handle = NULL;
  178.     status = ni_search_for_dir(S_SAMBADIR, ".", &list[levels].handle, &list[levels].dir, 5, 0, 0);
  179.     DEBUG(3,(" %s (%d)\n", (status == NI_OK)?"ok":"ERROR", status));
  180.  
  181.     while ((status == NI_OK) && (levels < 99)) {
  182.         levels++;
  183.         list[levels].handle = list[levels - 1].handle;
  184.         status = ni_search_for_dir(S_SAMBADIR, "..", &list[levels].handle, &list[levels].dir, 5, 0, 0);
  185.   }
  186.     
  187.     for (i = levels-1; i >= 0; i--) {
  188.         status = ni_addrtag(list[i].handle, &addr, &tag);
  189.         DEBUG(3,("Processing configurations from %s\n", tag));
  190.         ni_name_free(&tag);
  191.         bRetval |= ni_enumerate_sections(&list[i], sfunc, pfunc);
  192.         ni_free(list[i].handle);
  193.     }
  194.     
  195.     if (!bRetval) {
  196.         DEBUG(0,("pm_process (netinfo) retuned false. Trying flatfile %s.\n", pszFileName));
  197.         bRetval = pm_file_process(pszFileName, sfunc, pfunc);
  198.     }
  199.  
  200.     return (bRetval);
  201.     
  202. }
  203. #define pm_process    pm_file_process
  204. #endif
  205.  
  206. /**************************************************************************
  207. Strip all leading whitespace from a string.
  208. **************************************************************************/
  209. static void trimleft(char *psz)
  210. {
  211.    char *pszDest;
  212.  
  213.    pszDest = psz;
  214.    if (psz != NULL)
  215.    {
  216.       while (*psz != '\0' && isspace(*psz))
  217.      psz++;
  218.       while (*psz != '\0')
  219.      *pszDest++ = *psz++;
  220.       *pszDest = '\0';
  221.    }
  222. }
  223.  
  224. /**************************************************************************
  225. Strip all trailing whitespace from a string.
  226. **************************************************************************/
  227. static void trimright(char *psz)
  228. {
  229.    char *pszTemp;
  230.  
  231.    if (psz != NULL && psz[0] != '\0')
  232.    {
  233.       pszTemp = psz + strlen(psz) - 1;
  234.       while (isspace(*pszTemp))
  235.      *pszTemp-- = '\0';
  236.    }
  237. }
  238.  
  239. /***********************************************************************
  240. Collapse each whitespace area in a string to a single space.
  241. ***********************************************************************/
  242. static void collapse_spaces(char *psz)
  243. {
  244.    while (*psz)
  245.       if (isspace(*psz))
  246.       {
  247.      *psz++ = ' ';
  248.      trimleft(psz);
  249.       }
  250.       else
  251.      psz++;
  252. }
  253.  
  254. /**************************************************************************
  255. Return the value of the first non-white character in the specified string.
  256. The terminating NUL counts as non-white for the purposes of this function.
  257. Note - no check for a NULL string! What would we return?
  258. **************************************************************************/
  259. static int firstnonwhite(char *psz)
  260. {
  261.    while (isspace(*psz) && (*psz != '\0'))
  262.       psz++;
  263.    return (*psz);
  264. }
  265.  
  266.  
  267. /**************************************************************************
  268. Identifies all parameters in the current section, calls the parameter
  269. function for each. Ignores comment lines, stops and backs up in file when
  270. a section is encountered. Returns True on success, False on error.
  271. **************************************************************************/
  272. static BOOL enumerate_parameters(FILE *fileIn, BOOL (*pfunc)(char *,char *))
  273. {
  274.    pstring szBuf;
  275.    char *pszTemp;
  276.    BOOL bRetval;
  277.    long lFileOffset;
  278.    int  cTemp;
  279.    BOOL bParmFound;
  280.  
  281.    bRetval = False;
  282.    bParmFound = False;
  283.    while (True)
  284.    {
  285.       /* first remember where we are */
  286.       if ((lFileOffset = ftell(fileIn)) >= 0L)
  287.       {
  288.      /* then get and check a line */
  289.      if (fgets_slash(szBuf, sizeof(szBuf)-1, fileIn) == NULL)
  290.      {
  291.         /* stop - return OK unless file error */
  292.         bRetval = !ferror(fileIn);
  293.             if (!bRetval)
  294.           DEBUG(0,( "Read error on configuration file (enumerating parameters)!\n"));
  295.         break;   
  296.      }
  297.      else
  298.         /* if first non-white is a '[', stop (new section) */
  299.         if ((cTemp = firstnonwhite(szBuf)) == '[')
  300.         {
  301.            /* restore position to start of new section */
  302.            if (fseek(fileIn, lFileOffset, SEEK_SET) < 0L)
  303.            {
  304.                   DEBUG(0,( "Seek error on configuration file!\n"));
  305.                   break;
  306.            }
  307.  
  308.            /* return success */
  309.            bRetval = True;
  310.            break;
  311.         }
  312.         else
  313.            /* if it's a semicolon or line is blank, ignore the line */
  314.            if (!cTemp || strchr(";#",cTemp))
  315.            {
  316.           continue;
  317.            }
  318.            else
  319.           /* if no equals sign and line contains non-whitespace */
  320.           /* then line is badly formed */
  321.           if ((pszTemp = strchr(szBuf, '=')) == NULL)
  322.           {
  323.              DEBUG(0,( "Ignoring badly formed line: %s", szBuf));
  324.           }
  325.           else
  326.           {
  327.                      /* Note that we have found a parameter */
  328.                      bParmFound = True;
  329.              /* cut line at the equals sign */
  330.              *pszTemp++ = '\0';
  331.              /* trim leading and trailing space from both halves */
  332.              trimright(szBuf);
  333.              trimleft(szBuf);
  334.              trimright(pszTemp);
  335.              trimleft(pszTemp);
  336.              /* process the parameter iff passed pointer not NULL */
  337.              if (pfunc != NULL)
  338.                         if (!pfunc(szBuf, pszTemp))
  339.                break;
  340.           }
  341.       }
  342.    }
  343.    return (bRetval);
  344. }
  345.  
  346.  
  347. /***********************************************************************
  348. Close up s by n chars, at offset start.
  349. ***********************************************************************/
  350. static void closestr(char *s, int start, int n)
  351. {
  352.    char *src;
  353.    char *dest;
  354.    int  len;
  355.  
  356.    if (n > 0)
  357.       if ((src = dest = s) != NULL)
  358.       {
  359.          len = strlen(s);
  360.          if (start >= 0 && start < len - n)
  361.          {
  362.             src += start + n;
  363.             dest += start;
  364.   
  365.             while (*src)
  366.                *dest++ = *src++;
  367.             *dest = '\0';
  368.          }
  369.       }
  370. }
  371.  
  372. /**************************************************************************
  373. Identifies all sections in the parameter file, calls passed section_func()
  374. for each, passing the section name, then calls enumerate_parameters(). 
  375. Returns True on success, False on failure. Note that the section and 
  376. parameter names will have all internal whitespace areas collapsed to a 
  377. single space for processing.
  378. **************************************************************************/
  379. static BOOL enumerate_sections(FILE *fileIn,
  380.                    BOOL (*sfunc)(char *),BOOL (*pfunc)(char *,char *))
  381. {
  382.    pstring szBuf;
  383.    BOOL bRetval;
  384.    BOOL bSectionFound;
  385.  
  386.    /* this makes sure we get include lines right */
  387.    enumerate_parameters(fileIn, pfunc);
  388.  
  389.    bRetval = False;
  390.    bSectionFound = False;
  391.    while (True)
  392.    {
  393.       if (fgets_slash(szBuf, sizeof(szBuf)-1, fileIn) == NULL)
  394.       {
  395.      /* stop - return OK unless file error */
  396.      bRetval = !ferror(fileIn);
  397.          if (!bRetval)
  398.        DEBUG(0,( "Read error on configuration file (enumerating sections)!\n"));
  399.      break;   
  400.       }
  401.       else
  402.       {
  403.      trimleft(szBuf);
  404.      trimright(szBuf);
  405.      if (szBuf[0] == '[')
  406.      {
  407.         closestr(szBuf, 0, 1);
  408.         if (strlen(szBuf) > 1)
  409.            if (szBuf[strlen(szBuf) - 1] == ']')
  410.            {  
  411.           /* found a section - note the fact */
  412.                   bSectionFound = True;
  413.           /* remove trailing metabracket */
  414.           szBuf[strlen(szBuf) - 1] = '\0';
  415.           /* remove leading and trailing whitespace from name */
  416.           trimleft(szBuf);
  417.           trimright(szBuf);
  418.           /* reduce all internal whitespace to one space */
  419.           collapse_spaces(szBuf);
  420.           /* process it - stop if the processing fails */
  421.           if (sfunc != NULL)
  422.                      if (!sfunc(szBuf))
  423.                 break;
  424.           if (!enumerate_parameters(fileIn, pfunc))
  425.                      break;
  426.            }
  427.      }
  428.       }
  429.    }
  430.  
  431.    return (bRetval);
  432. }
  433.  
  434. /**************************************************************************
  435. Process the passed parameter file.
  436.  
  437. Returns True if successful, else False.
  438. **************************************************************************/
  439. BOOL pm_process(char *pszFileName,BOOL (*sfunc)(char *),BOOL (*pfunc)(char *,char *))
  440. {
  441.    FILE *fileIn;
  442.    BOOL bRetval;
  443.  
  444.    bRetval = False;
  445.  
  446.    /* record the filename for use in error messages one day... */
  447.    pszParmFile = pszFileName;
  448.  
  449.    if (pszParmFile == NULL || strlen(pszParmFile) < 1)
  450.       DEBUG(0,( "No configuration filename specified!\n"));
  451.    else
  452.       if ((fileIn = fopen(pszParmFile, "r")) == NULL)
  453.          DEBUG(0,( "Unable to open configuration file \"%s\"!\n", pszParmFile));
  454.       else
  455.       {
  456.          DEBUG(3,("Processing configuration file \"%s\"\n", pszParmFile));
  457.      bRetval = enumerate_sections(fileIn, sfunc, pfunc);
  458.      fclose(fileIn);
  459.       }
  460.  
  461.    if (!bRetval)
  462.      DEBUG(0,("pm_process retuned false\n"));
  463.    return (bRetval);
  464. }
  465.  
  466.