1 //
2 // $Id: conffile.cc,v 1.1 2000/09/21 09:44:53 voeckler Exp $
3 //
4 // Author:  Jens-S. V�ckler <voeckler@rvs.uni-hannover.de>
5 //
6 // File:    conffile.cc
7 //          Fri Sep 15 2000
8 //
9 // (c) 2000 Lehrgebiet Rechnernetze und Verteilte Systeme
10 //          Universit�t Hannover, Germany
11 //
12 // Permission to use, copy, modify, distribute, and sell this software
13 // and its documentation for any purpose is hereby granted without fee,
14 // provided that (i) the above copyright notices and this permission
15 // notice appear in all copies of the software and related documentation,
16 // and (ii) the names of the Lehrgebiet Rechnernetze und Verteilte
17 // Systeme and the University of Hannover may not be used in any
18 // advertising or publicity relating to the software without the
19 // specific, prior written permission of Lehrgebiet Rechnernetze und
20 // Verteilte Systeme and the University of Hannover.
21 //
22 // THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
24 // WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
25 //
26 // IN NO EVENT SHALL THE LEHRGEBIET RECHNERNETZE UND VERTEILTE SYSTEME OR
27 // THE UNIVERSITY OF HANNOVER BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
28 // INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES
29 // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT
30 // ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY,
31 // ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
32 // SOFTWARE.
33 //
34 // $Log: conffile.cc,v $
35 // Revision 1.1  2000/09/21 09:44:53  voeckler
36 // Initial revision
37 //
38 //
39 #if defined(__GNUC__) || defined(__GNUG__)
40 #pragma implementation
41 #endif
42 
43 #include "conffile.hh"
44 #include <sys/types.h>
45 #include <errno.h>
46 #include <memory.h>
47 #include <string.h>
48 #include <stdlib.h>
49 #include <stdio.h>
50 #include <regex.h>
51 
52 int
readConfigFile(CacheDirVector & cachedir,const char * fn,FILE * debug)53 readConfigFile( CacheDirVector& cachedir, const char* fn, FILE* debug )
54   // purpose: read squid.conf file and extract cache_dir entries
55   // paramtr: cachedir (OUT): vector with an entry for each cache_dir found
56   //          fn (IN): file name of squid.conf to use
57   // returns: number of entries, or negative to warn of errors
58 {
59   static const char* expression =
60     "^[ \t]*cache_dir([ \t]+([[:alpha:]]+))?[ \t]+([[:graph:]]+)[ \t]+([0-9]+)[ \t]+([0-9]+)[ \t]+([0-9]+)";
61 
62   // try to open file
63   if ( debug ) fprintf( debug, "# trying to open %s\n", fn ? fn : "(null)" );
64   FILE* in = fopen( fn, "r" );
65   if ( in == NULL ) {
66     fprintf( stderr, "fopen %s: %s\n", fn, strerror(errno) );
67     return -1;
68   }
69 
70   // prepare regular expression for matching
71   if ( debug ) fprintf( debug, "# trying to compile \"%s\"\n", expression );
72   regex_t rexp;
73   int result = regcomp( &rexp, expression, REG_EXTENDED );
74   if ( result != 0 ) {
75     char buffer[256];
76     regerror( result, &rexp, buffer, sizeof(buffer) );
77     fprintf( stderr, "regular expression \"%s\": %s\n", expression, buffer );
78     return -1;
79   }
80 
81   // read line by line
82   if ( debug ) fputs( "# trying to read lines\n", debug );
83 
84   regmatch_t subs[8];
85   char *s, line[1024];
86   CacheDir cd;
87   while ( fgets( line, sizeof(line), in ) ) {
88     // FIXME: overly long lines
89 
90     // terminate line at start of comment
91     if ( (s = (char*) memchr( line, '#', sizeof(line) )) ) *s = '\0';
92 
93     // quick skip
94     if ( *line == '\0' || *line == '\n' ) continue;
95 
96     // test line
97     if ( (result=regexec( &rexp, line, 7, subs, 0 )) != 0 ) {
98       // error or no match
99       if ( result != REG_NOMATCH ) {
100 	char buffer[256];
101 	regerror( result, &rexp, buffer, sizeof(buffer) );
102 	fprintf( stderr, "while matching \"%s\" against %s%s\n",
103 		 expression, line, buffer );
104 	regfree(&rexp);
105 	fclose(in);
106 	return -1;
107       }
108     } else {
109       // match, please record
110       memset( &cd, 0, sizeof(cd) );
111       if ( debug ) fprintf( debug, "# match from %d-%d on line %s",
112 			    subs[0].rm_so, subs[0].rm_eo, line );
113 
114       // terminate line after matched expression
115       line[ subs[0].rm_eo ] = '\0';
116 
117       // extract information. If 6th parenthesis is filled, this is
118       // a new squid with disk types, otherwise it is an older version
119       int offset = 2;
120       if ( subs[6].rm_so == -1 ) {
121 	// old version, disk type at position 2 is always UFS
122 	cd.type = CacheDir::CDT_UFS;
123       } else {
124 	// new version, disk type at position 2
125 	line[ subs[offset].rm_eo ] = '\0';
126 	if ( debug ) fprintf( debug, "# match from %d-%d on \"%s\"\n",
127 			      subs[offset].rm_so, subs[offset].rm_eo,
128 			      line+subs[offset].rm_so );
129 	if ( strcmp( line + subs[offset].rm_so, "ufs" ) == 0 )
130 	  cd.type = CacheDir::CDT_UFS;
131 	else if ( strcmp( line + subs[offset].rm_so, "asyncufs" ) == 0 )
132 	  cd.type = CacheDir::CDT_AUFS;
133 	else if ( strcmp( line + subs[offset].rm_so, "diskd" ) == 0 )
134 	  cd.type = CacheDir::CDT_DISKD;
135 	else
136 	  cd.type = CacheDir::CDT_OTHER;
137 	offset++;
138       }
139 
140       // extract base directory
141       line[ subs[offset].rm_eo ] = '\0';
142       if ( debug ) fprintf( debug, "# match from %d-%d on \"%s\"\n",
143 			    subs[offset].rm_so, subs[offset].rm_eo,
144 			    line+subs[offset].rm_so );
145       cd.base = strdup( line+subs[offset].rm_so );
146       offset++;
147 
148       // extract size information
149       line[ subs[offset].rm_eo ] = '\0';
150       if ( debug ) fprintf( debug, "# match from %d-%d on \"%s\"\n",
151 			    subs[offset].rm_so, subs[offset].rm_eo,
152 			    line+subs[offset].rm_so );
153       cd.size = strtoul( line+subs[offset].rm_so, 0, 10 );
154       offset++;
155 
156       // extract 1st level directories
157       line[ subs[offset].rm_eo ] = '\0';
158       if ( debug ) fprintf( debug, "# match from %d-%d on \"%s\"\n",
159 			    subs[offset].rm_so, subs[offset].rm_eo,
160 			    line+subs[offset].rm_so );
161       cd.level[0] = strtoul( line+subs[offset].rm_so, 0, 10 );
162       offset++;
163 
164       // extract 2nd level directories
165       line[ subs[offset].rm_eo ] = '\0';
166       if ( debug ) fprintf( debug, "# match from %d-%d on \"%s\"\n",
167 			    subs[offset].rm_so, subs[offset].rm_eo,
168 			    line+subs[offset].rm_so );
169       cd.level[1] = strtoul( line+subs[offset].rm_so, 0, 10 );
170       offset++;
171 
172       cachedir.push_back( cd );
173     }
174   }
175 
176   fclose(in);
177   regfree(&rexp);
178   return cachedir.size();
179 }
180