XRootD
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"
42 #include "XrdOuc/XrdOucStream.hh"
43 #include "XrdOuc/XrdOucString.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 
53 {
58 char *gBuff = 0;
59 bool echobfr = false;
60 
62  : Tokenizer(0), eDest(eP) {}
64 };
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  delete gcP;
115 }
116 
117 /******************************************************************************/
118 /* E c h o L i n e */
119 /******************************************************************************/
120 
122 {
123 
124 // Make sure we can actually display anything
125 //
126  if (!(gcP->eDest))
127  throw std::invalid_argument("XrdSysError object not supplied!");
128 
129 // Echo only when we have something to echo
130 //
131  if (gcP->lline.length()) gcP->eDest->Say("=====> ", gcP->lline.c_str());
132 }
133 
134 /******************************************************************************/
135 /* E c h o O r d e r */
136 /******************************************************************************/
137 
138 void XrdOucGatherConf::EchoOrder(bool doBefore)
139 {
140  gcP->echobfr = doBefore;
141 }
142 
143 /******************************************************************************/
144 /* G a t h e r */
145 /******************************************************************************/
146 
147 int XrdOucGatherConf::Gather(const char *cfname, Level lvl, const char *parms)
148 {
149  XrdOucEnv myEnv;
150  XrdOucStream Config(gcP->eDest, getenv("XRDINSTANCE"), &myEnv, "=====> ");
151  XrdOucTList *tP;
152  XrdOucString theGrab;
153  char *var, drctv[64], body[4096];
154  int cfgFD, n, rc;
155  bool trim = false, addKey = true;
156 
157 // Make sure we have something to compare
158 //
159  if (!(gcP->Match)) return 0;
160 
161 // Reset the buffer if it has been set
162 //
163  if (gcP->gBuff)
164  {free(gcP->gBuff);
165  gcP->gBuff = 0;
166  gcP->Tokenizer.Attach(0);
167  }
168 
169 // Open the config file
170 //
171  if ( (cfgFD = open(cfname, O_RDONLY, 0)) < 0)
172  {rc = errno;
173  if (gcP->eDest) gcP->eDest->Emsg("Gcf", rc, "open config file", cfname);
174  return -rc;
175  }
176 
177 // Attach the file to our stream object and size the grab buffer
178 //
179  Config.Attach(cfgFD, 4096);
180  theGrab.resize(4096);
181  if (parms && *parms) theGrab = parms;
182 
183 // Setup for processing
184 //
185  switch(lvl)
186  {case full_lines: *drctv = '\n'; trim = false; addKey = true; break;
187  case trim_lines: *drctv = '\n'; trim = true; addKey = true; break;
188  case only_body: *drctv = ' '; trim = false; addKey = false; break;
189  case trim_body: *drctv = ' '; trim = true; addKey = true; break;
190  default: break; return 0; // Should never happen
191  break;
192  }
193 
194 // Process the config file
195 //
196  while((var = Config.GetMyFirstWord()))
197  {tP = gcP->Match;
198  while(tP && ((tP->val && strncmp(var, tP->text, tP->val)) ||
199  (!tP->val && strcmp( var, tP->text)))) tP = tP->next;
200 
201  if (tP)
202  {if (addKey)
203  {if (trim)
204  {char *dot = index(var, '.');
205  if (dot && *(dot+1)) var = dot+1;
206  }
207  int n = snprintf(drctv+1, sizeof(drctv)-1, "%s ", var);
208  if (n >= (int)sizeof(drctv)-1)
209  {if (gcP->eDest) gcP->eDest->Emsg("Gcf", E2BIG, "handle", var);
210  return -E2BIG;
211  }
212  } else drctv[1] = 0;
213 
214  if (!Config.GetRest(body, sizeof(body)))
215  {if (gcP->eDest) gcP->eDest->Emsg("Gcf", E2BIG, "handle arguments");
216  return -E2BIG;
217  }
218 
219  if (*body || addKey)
220  {theGrab += drctv;
221  theGrab += body;
222  }
223  }
224  }
225 
226 // Now check if any errors occurred during file i/o
227 //
228  if ((rc = Config.LastError()))
229  {if (gcP->eDest) gcP->eDest->Emsg("Gcf", rc, "read config file", cfname);
230  return (rc < 0 ? rc : -rc);
231  }
232 
233 
234 // Copy the grab to a modifiable buffer.
235 //
236  if ((n = theGrab.length()) <= 1) n = 0;
237  else {gcP->gBuff = (char *)malloc(n);
238  strcpy(gcP->gBuff, theGrab.c_str()+1); // skip 1st byte but add null
239  gcP->Tokenizer.Attach(gcP->gBuff);
240  n--;
241  }
242  return n;
243 }
244 
245 /******************************************************************************/
246 /* G e t L i n e */
247 /******************************************************************************/
248 
250 {
251  char* theLine = gcP->Tokenizer.GetLine();
252 
253  while(theLine && *theLine == 0) theLine = gcP->Tokenizer.GetLine();
254 
255  if (!theLine) gcP->lline = "";
256  else gcP->lline = theLine;
257 
258  return theLine;
259 }
260 
261 /******************************************************************************/
262 /* G e t T o k e n */
263 /******************************************************************************/
264 
265 char* XrdOucGatherConf::GetToken(char **rest, int lowcase)
266 {
267  return gcP->Tokenizer.GetToken(rest, lowcase);
268 }
269 
270 /******************************************************************************/
271 /* h a s D a t a */
272 /******************************************************************************/
273 
275 {
276  return gcP->gBuff != 0 && *(gcP->gBuff) != 0;
277 }
278 
279 /******************************************************************************/
280 /* L a s t L i n e */
281 /******************************************************************************/
282 
284 {
285  if (gcP->lline.capacity() == 0) return "";
286  return gcP->lline.c_str();
287 }
288 
289 /******************************************************************************/
290 /* M s g E */
291 /******************************************************************************/
292 
293 void XrdOucGatherConf::MsgE(const char* txt1,const char* txt2,const char* txt3,
294  const char* txt4,const char* txt5,const char* txt6)
295 {
296  const char* mVec[7];
297  int n = 0;
298 
299  mVec[n++] = "Config mistake:";
300  if (txt1) mVec[n++] = txt1;
301  if (txt2) mVec[n++] = txt2;
302  if (txt3) mVec[n++] = txt3;
303  if (txt4) mVec[n++] = txt4;
304  if (txt5) mVec[n++] = txt5;
305  if (txt6) mVec[n++] = txt6;
306 
307  MsgX(mVec, n+1);
308 }
309 
310 /******************************************************************************/
311 /* M s g W */
312 /******************************************************************************/
313 
314 void XrdOucGatherConf::MsgW(const char* txt1,const char* txt2,const char* txt3,
315  const char* txt4,const char* txt5,const char* txt6)
316 {
317  const char* mVec[7];
318  int n = 0;
319 
320  mVec[n++] = "Config warning:";
321  if (txt1) mVec[n++] = txt1;
322  if (txt2) mVec[n++] = txt2;
323  if (txt3) mVec[n++] = txt3;
324  if (txt4) mVec[n++] = txt4;
325  if (txt5) mVec[n++] = txt5;
326  if (txt6) mVec[n++] = txt6;
327 
328  MsgX(mVec, n+1);
329 }
330 
331 /******************************************************************************/
332 /* M s g X */
333 /******************************************************************************/
334 
335 void XrdOucGatherConf::MsgX(const char** mVec, int n)
336 {
337  XrdOucString theMsg(2048);
338 
339 // Make sure we can actually display anything
340 //
341  if (!(gcP->eDest))
342  throw std::invalid_argument("XrdSysError object not supplied!");
343 
344 // Construct the message in a string
345 //
346  for (int i = 0; i < n; i++)
347  {theMsg += mVec[i];
348  if (i+1 < n) theMsg += ' ';
349  }
350 
351 // Dislay the last line and the message in the proper order
352 //
353  if (gcP->echobfr) EchoLine();
354  gcP->eDest->Say(theMsg.c_str());
355  if (!(gcP->echobfr)) EchoLine();
356 }
357 
358 /******************************************************************************/
359 /* M s g f E */
360 /******************************************************************************/
361 
362 void XrdOucGatherConf::MsgfE(const char *fmt, ...)
363 {
364  char buffer[2048];
365  va_list args;
366  va_start (args, fmt);
367 
368 // Format the message
369 //
370  vsnprintf(buffer, sizeof(buffer), fmt, args);
371 
372 // Go print the message
373 //
374  MsgfX("Config mistake: ", buffer);
375 }
376 
377 /******************************************************************************/
378 /* M s g f W */
379 /******************************************************************************/
380 
381 void XrdOucGatherConf::MsgfW(const char *fmt, ...)
382 {
383  char buffer[2048];
384  va_list args;
385  va_start (args, fmt);
386 
387 // Format the message
388 //
389  vsnprintf(buffer, sizeof(buffer), fmt, args);
390 
391 // Go print the message
392 //
393  MsgfX("Config warning: ", buffer);
394 }
395 
396 /******************************************************************************/
397 /* M s g f X */
398 /******************************************************************************/
399 
400 void XrdOucGatherConf::MsgfX(const char* txt1, const char* txt2)
401 {
402 
403 // Make sure we can actually display anything
404 //
405  if (!(gcP->eDest))
406  throw std::invalid_argument("XrdSysError object not supplied!");
407 
408 // Dislay the last line and the message in the proper order
409 //
410  if (gcP->echobfr) EchoLine();
411  gcP->eDest->Say(txt1, txt2);
412  if (!(gcP->echobfr)) EchoLine();
413 }
414 
415 /******************************************************************************/
416 /* R e t T o k e n */
417 /******************************************************************************/
418 
420 {
421  return gcP->Tokenizer.RetToken();
422 }
423 
424 /******************************************************************************/
425 /* T a b s */
426 /******************************************************************************/
427 
429 {
430  gcP->Tokenizer.Tabs(x);
431 }
432 
433 /******************************************************************************/
434 /* u s e D a t a */
435 /******************************************************************************/
436 
437 bool XrdOucGatherConf::useData(const char *data)
438 {
439  if (!data || *data == 0) return false;
440 
441  if (gcP->gBuff) free(gcP->gBuff);
442  gcP->gBuff = strdup(data);
443  gcP->Tokenizer.Attach(gcP->gBuff);
444  return true;
445 }
void trim(std::string &str)
Definition: XrdHttpReq.cc:77
#define open
Definition: XrdPosix.hh:76
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)
void Tabs(int x=1)
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.
const char * c_str() const
int capacity() const
bool endswith(char c)
int length() const
void resize(int lmx=0)
XrdOucTList * next
Definition: XrdOucTList.hh:45
char * text
Definition: XrdOucTList.hh:46
void Tabs(int x=1)
char * GetToken(char **rest=0, int lowcase=0)
void Attach(char *bp)
int Emsg(const char *esfx, int ecode, const char *text1, const char *text2=0)
Definition: XrdSysError.cc:95
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)
Definition: XrdSysError.cc:141
XrdCmsConfig Config
XrdOucTokenizer Tokenizer
XrdOucGatherConfData(XrdSysError *eP)