XRootD
Loading...
Searching...
No Matches
XrdOucGatherConf.cc
Go to the documentation of this file.
1/******************************************************************************/
2/* */
3/* X r d O u c G a t h e r C o n f . c c */
4/* */
5/* (c) 2021 by the Board of Trustees of the Leland Stanford, Jr., University */
6/* Produced by Andrew Hanushevsky for Stanford University under contract */
7/* DE-AC02-76-SFO0515 with the Deprtment of Energy */
8/* */
9/* This file is part of the XRootD software suite. */
10/* */
11/* XRootD is free software: you can redistribute it and/or modify it under */
12/* the terms of the GNU Lesser General Public License as published by the */
13/* Free Software Foundation, either version 3 of the License, or (at your */
14/* option) any later version. */
15/* */
16/* XRootD is distributed in the hope that it will be useful, but WITHOUT */
17/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
18/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public */
19/* License for more details. */
20/* */
21/* You should have received a copy of the GNU Lesser General Public License */
22/* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */
23/* COPYING (GPL license). If not, see <http://www.gnu.org/licenses/>. */
24/* */
25/* The copyright holder's institutional names and contributor's names may not */
26/* be used to endorse or promote products derived from this software without */
27/* specific prior written permission of the institution or contributor. */
28/******************************************************************************/
29
30#include <stdexcept>
31
32#include <fcntl.h>
33#include <stdio.h>
34#include <stdlib.h>
35#include <string.h>
36#include <strings.h>
37#include <sys/stat.h>
38#include <sys/types.h>
39
40#include "XrdOuc/XrdOucEnv.hh"
44#include "XrdOuc/XrdOucTList.hh"
46#include "XrdSys/XrdSysError.hh"
47
48/******************************************************************************/
49/* L o c a l O b j e c t s */
50/******************************************************************************/
51
65
66/******************************************************************************/
67/* C o n s t r u c t o r # 1 */
68/******************************************************************************/
69
71 : gcP(new XrdOucGatherConfData(errP))
72{
73 XrdOucString wlist(want), wtoken;
74 int wlen, wPos = 0;
75
76 while((wPos = wlist.tokenize(wtoken, wPos, ' ')) != -1)
77 {wlen = (wtoken.endswith('.') ? wtoken.length() : 0);
78 gcP->Match = new XrdOucTList(wtoken.c_str(), wlen, gcP->Match);
79 }
80}
81
82/******************************************************************************/
83/* C o n s t r u c t o r # 2 */
84/******************************************************************************/
85
87 : gcP(new XrdOucGatherConfData(errP))
88{
89 int n, i = 0;
90
91 while(want[i])
92 {if ((n = strlen(want[i])))
93 {if (*(want[i]+(n-1)) != '.') n = 0;
94 gcP->Match = new XrdOucTList(want[i], n, gcP->Match);
95 }
96 }
97}
98
99/******************************************************************************/
100/* D e s t r u c t o r */
101/******************************************************************************/
102
104{
105 XrdOucTList *tP;
106
107 while((tP = gcP->Match))
108 {gcP->Match = tP->next;
109 delete tP;
110 }
111
112 if (gcP->gBuff) free(gcP->gBuff);
113}
114
115/******************************************************************************/
116/* E c h o L i n e */
117/******************************************************************************/
118
120{
121
122// Make sure we can actually display anything
123//
124 if (!(gcP->eDest))
125 throw std::invalid_argument("XrdSysError object not supplied!");
126
127// Echo only when we have something to echo
128//
129 if (gcP->lline.length()) gcP->eDest->Say("=====> ", gcP->lline.c_str());
130}
131
132/******************************************************************************/
133/* E c h o O r d e r */
134/******************************************************************************/
135
137{
138 gcP->echobfr = doBefore;
139}
140
141/******************************************************************************/
142/* G a t h e r */
143/******************************************************************************/
144
145int XrdOucGatherConf::Gather(const char *cfname, Level lvl, const char *parms)
146{
147 XrdOucEnv myEnv;
148 XrdOucStream Config(gcP->eDest, getenv("XRDINSTANCE"), &myEnv, "=====> ");
149 XrdOucTList *tP;
150 XrdOucString theGrab;
151 char *var, drctv[64], body[4096];
152 int cfgFD, n, rc;
153 bool trim = false, addKey = true;
154
155// Make sure we have something to compare
156//
157 if (!(gcP->Match)) return 0;
158
159// Reset the buffer if it has been set
160//
161 if (gcP->gBuff)
162 {free(gcP->gBuff);
163 gcP->gBuff = 0;
164 gcP->Tokenizer.Attach(0);
165 }
166
167// Open the config file
168//
169 if ( (cfgFD = open(cfname, O_RDONLY, 0)) < 0)
170 {rc = errno;
171 if (gcP->eDest) gcP->eDest->Emsg("Gcf", rc, "open config file", cfname);
172 return -rc;
173 }
174
175// Attach the file to our stream object and size the grab buffer
176//
177 Config.Attach(cfgFD, 4096);
178 theGrab.resize(4096);
179 if (parms && *parms) theGrab = parms;
180
181// Setup for processing
182//
183 switch(lvl)
184 {case full_lines: *drctv = '\n'; trim = false; addKey = true; break;
185 case trim_lines: *drctv = '\n'; trim = true; addKey = true; break;
186 case only_body: *drctv = ' '; trim = false; addKey = false; break;
187 case trim_body: *drctv = ' '; trim = true; addKey = true; break;
188 default: break; return 0; // Should never happen
189 break;
190 }
191
192// Process the config file
193//
194 while((var = Config.GetMyFirstWord()))
195 {tP = gcP->Match;
196 while(tP && ((tP->val && strncmp(var, tP->text, tP->val)) ||
197 (!tP->val && strcmp( var, tP->text)))) tP = tP->next;
198
199 if (tP)
200 {if (addKey)
201 {if (trim)
202 {char *dot = index(var, '.');
203 if (dot && *(dot+1)) var = dot+1;
204 }
205 int n = snprintf(drctv+1, sizeof(drctv)-1, "%s ", var);
206 if (n >= (int)sizeof(drctv)-1)
207 {if (gcP->eDest) gcP->eDest->Emsg("Gcf", E2BIG, "handle", var);
208 return -E2BIG;
209 }
210 } else drctv[1] = 0;
211
212 if (!Config.GetRest(body, sizeof(body)))
213 {if (gcP->eDest) gcP->eDest->Emsg("Gcf", E2BIG, "handle arguments");
214 return -E2BIG;
215 }
216
217 if (*body || addKey)
218 {theGrab += drctv;
219 theGrab += body;
220 }
221 }
222 }
223
224// Now check if any errors occurred during file i/o
225//
226 if ((rc = Config.LastError()))
227 {if (gcP->eDest) gcP->eDest->Emsg("Gcf", rc, "read config file", cfname);
228 return (rc < 0 ? rc : -rc);
229 }
230
231
232// Copy the grab to a modifiable buffer.
233//
234 if ((n = theGrab.length()) <= 1) n = 0;
235 else {gcP->gBuff = (char *)malloc(n);
236 strcpy(gcP->gBuff, theGrab.c_str()+1); // skip 1st byte but add null
237 gcP->Tokenizer.Attach(gcP->gBuff);
238 n--;
239 }
240 return n;
241}
242
243/******************************************************************************/
244/* G e t L i n e */
245/******************************************************************************/
246
248{
249 char* theLine = gcP->Tokenizer.GetLine();
250
251 while(theLine && *theLine == 0) theLine = gcP->Tokenizer.GetLine();
252
253 if (!theLine) gcP->lline = "";
254 else gcP->lline = theLine;
255
256 return theLine;
257}
258
259/******************************************************************************/
260/* G e t T o k e n */
261/******************************************************************************/
262
263char* XrdOucGatherConf::GetToken(char **rest, int lowcase)
264{
265 return gcP->Tokenizer.GetToken(rest, lowcase);
266}
267
268/******************************************************************************/
269/* h a s D a t a */
270/******************************************************************************/
271
273{
274 return gcP->gBuff != 0 && *(gcP->gBuff) != 0;
275}
276
277/******************************************************************************/
278/* L a s t L i n e */
279/******************************************************************************/
280
282{
283 if (gcP->lline.capacity() == 0) return "";
284 return gcP->lline.c_str();
285}
286
287/******************************************************************************/
288/* M s g E */
289/******************************************************************************/
290
291void XrdOucGatherConf::MsgE(const char* txt1,const char* txt2,const char* txt3,
292 const char* txt4,const char* txt5,const char* txt6)
293{
294 const char* mVec[7];
295 int n = 0;
296
297 mVec[n++] = "Config mistake:";
298 if (txt1) mVec[n++] = txt1;
299 if (txt2) mVec[n++] = txt2;
300 if (txt3) mVec[n++] = txt3;
301 if (txt4) mVec[n++] = txt4;
302 if (txt5) mVec[n++] = txt5;
303 if (txt6) mVec[n++] = txt6;
304
305 MsgX(mVec, n+1);
306}
307
308/******************************************************************************/
309/* M s g W */
310/******************************************************************************/
311
312void XrdOucGatherConf::MsgW(const char* txt1,const char* txt2,const char* txt3,
313 const char* txt4,const char* txt5,const char* txt6)
314{
315 const char* mVec[7];
316 int n = 0;
317
318 mVec[n++] = "Config warning:";
319 if (txt1) mVec[n++] = txt1;
320 if (txt2) mVec[n++] = txt2;
321 if (txt3) mVec[n++] = txt3;
322 if (txt4) mVec[n++] = txt4;
323 if (txt5) mVec[n++] = txt5;
324 if (txt6) mVec[n++] = txt6;
325
326 MsgX(mVec, n+1);
327}
328
329/******************************************************************************/
330/* M s g X */
331/******************************************************************************/
332
333void XrdOucGatherConf::MsgX(const char** mVec, int n)
334{
335 XrdOucString theMsg(2048);
336
337// Make sure we can actually display anything
338//
339 if (!(gcP->eDest))
340 throw std::invalid_argument("XrdSysError object not supplied!");
341
342// Construct the message in a string
343//
344 for (int i = 0; i < n; i++)
345 {theMsg += mVec[i];
346 if (i+1 < n) theMsg += ' ';
347 }
348
349// Dislay the last line and the message in the proper order
350//
351 if (gcP->echobfr) EchoLine();
352 gcP->eDest->Say(theMsg.c_str());
353 if (!(gcP->echobfr)) EchoLine();
354}
355
356/******************************************************************************/
357/* M s g f E */
358/******************************************************************************/
359
360void XrdOucGatherConf::MsgfE(const char *fmt, ...)
361{
362 char buffer[2048];
363 va_list args;
364 va_start (args, fmt);
365
366// Format the message
367//
368 vsnprintf(buffer, sizeof(buffer), fmt, args);
369
370// Go print the message
371//
372 MsgfX("Config mistake: ", buffer);
373}
374
375/******************************************************************************/
376/* M s g f W */
377/******************************************************************************/
378
379void XrdOucGatherConf::MsgfW(const char *fmt, ...)
380{
381 char buffer[2048];
382 va_list args;
383 va_start (args, fmt);
384
385// Format the message
386//
387 vsnprintf(buffer, sizeof(buffer), fmt, args);
388
389// Go print the message
390//
391 MsgfX("Config warning: ", buffer);
392}
393
394/******************************************************************************/
395/* M s g f X */
396/******************************************************************************/
397
398void XrdOucGatherConf::MsgfX(const char* txt1, const char* txt2)
399{
400
401// Make sure we can actually display anything
402//
403 if (!(gcP->eDest))
404 throw std::invalid_argument("XrdSysError object not supplied!");
405
406// Dislay the last line and the message in the proper order
407//
408 if (gcP->echobfr) EchoLine();
409 gcP->eDest->Say(txt1, txt2);
410 if (!(gcP->echobfr)) EchoLine();
411}
412
413/******************************************************************************/
414/* R e t T o k e n */
415/******************************************************************************/
416
418{
419 return gcP->Tokenizer.RetToken();
420}
421
422/******************************************************************************/
423/* T a b s */
424/******************************************************************************/
425
427{
428 gcP->Tokenizer.Tabs(x);
429}
430
431/******************************************************************************/
432/* u s e D a t a */
433/******************************************************************************/
434
435bool XrdOucGatherConf::useData(const char *data)
436{
437 if (!data || *data == 0) return false;
438
439 if (gcP->gBuff) free(gcP->gBuff);
440 gcP->gBuff = strdup(data);
441 gcP->Tokenizer.Attach(gcP->gBuff);
442 return true;
443}
void trim(std::string &str)
Definition XrdHttpReq.cc:76
#define open
Definition XrdPosix.hh:71
char * GetToken(char **rest=0, int lowcase=0)
XrdOucGatherConf(const char *want, XrdSysError *errP=0)
void MsgfW(const char *fmt,...)
void MsgW(const char *txt1, const char *txt2=0, const char *txt3=0, const char *txt4=0, const char *txt5=0, const char *txt6=0)
void MsgfE(const char *fmt,...)
int Gather(const char *cfname, Level lvl, const char *parms=0)
void MsgE(const char *txt1, const char *txt2=0, const char *txt3=0, const char *txt4=0, const char *txt5=0, const char *txt6=0)
void EchoOrder(bool doBefore)
const char * LastLine()
bool useData(const char *data)
@ trim_lines
Prefix trimmed lines.
@ trim_body
Prefix trimmed lines as a string blob.
@ only_body
Only directive bodies as a string blob.
@ full_lines
Complete lines.
bool endswith(char c)
int length() const
void resize(int lmx=0)
const char * c_str() const
XrdOucTList * next
void Say(const char *text1, const char *text2=0, const char *txt3=0, const char *text4=0, const char *text5=0, const char *txt6=0)
XrdOucTokenizer Tokenizer
XrdOucGatherConfData(XrdSysError *eP)