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 
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 
136 void XrdOucGatherConf::EchoOrder(bool doBefore)
137 {
138  gcP->echobfr = doBefore;
139 }
140 
141 /******************************************************************************/
142 /* G a t h e r */
143 /******************************************************************************/
144 
145 int 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 
263 char* 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 
291 void 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 
312 void 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 
333 void 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 
360 void 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 
379 void 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 
398 void 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 
435 bool 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
int open(const char *path, int oflag,...)
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)