XrdOucUtils.cc

Go to the documentation of this file.
00001 /******************************************************************************/
00002 /*                                                                            */
00003 /*                        X r d O u c U t i l s . c c                         */
00004 /*                                                                            */
00005 /* (c) 2005 by the Board of Trustees of the Leland Stanford, Jr., University  */
00006 /*                            All Rights Reserved                             */
00007 /*   Produced by Andrew Hanushevsky for Stanford University under contract    */
00008 /*              DE-AC02-76-SFO0515 with the Department of Energy              */
00009 /******************************************************************************/
00010 
00011 //         $Id: XrdOucUtils.cc 35287 2010-09-14 21:19:35Z ganis $
00012 
00013 const char *XrdOucUtilsCVSID = "$Id: XrdOucUtils.cc 35287 2010-09-14 21:19:35Z ganis $";
00014 
00015 #include <ctype.h>
00016 #include <errno.h>
00017 #include <stdio.h>
00018 
00019 #ifdef WIN32
00020 #include <direct.h>
00021 #include "XrdSys/XrdWin32.hh"
00022 #else
00023 #include <fcntl.h>
00024 #include <sys/stat.h>
00025 #include <sys/types.h>
00026 #endif
00027 #include "XrdNet/XrdNetDNS.hh"
00028 #include "XrdSys/XrdSysError.hh"
00029 #include "XrdOuc/XrdOucStream.hh"
00030 #include "XrdSys/XrdSysPlatform.hh"
00031 #include "XrdOuc/XrdOucUtils.hh"
00032   
00033 /******************************************************************************/
00034 /*                                 e T e x t                                  */
00035 /******************************************************************************/
00036   
00037 // eText() returns the text associated with the error, making the first
00038 // character in the text lower case. The text buffer pointer is returned.
00039 
00040 char *XrdOucUtils::eText(int rc, char *eBuff, int eBlen, int AsIs)
00041 {
00042    const char *etP;
00043 
00044 // Get error text
00045 //
00046    if (!(etP = strerror(rc)) || !(*etP)) etP = "reason unknown";
00047 
00048 // Copy the text and lower case the first letter
00049 //
00050    strlcpy(eBuff, etP, eBlen);
00051    if (!AsIs) *eBuff = tolower(*eBuff);
00052 
00053 // All done
00054 //
00055    return eBuff;
00056 }
00057 
00058 /******************************************************************************/
00059 /*                                  d o I f                                   */
00060 /******************************************************************************/
00061   
00062 // doIf() parses "if [<hostlist>] [<altopt> [&& <altop> [ ... ]]]"
00063 // altop: [exec <pgmlist> [&& named <namelist>]] | [named <namelist>]
00064 
00065 // Returning 1 if true (i.e., this machine is one of the named hosts in hostlist 
00066 // and is running one of the programs pgmlist and named by one of the names in 
00067 // namelist).
00068 // Return -1 (negative truth) if an error occured.
00069 // Otherwise, returns false (0). Some combination of hostlist, pgm, and 
00070 // namelist, must be specified.
00071 
00072 int XrdOucUtils::doIf(XrdSysError *eDest, XrdOucStream &Config,
00073                       const char *what,  const char *hname,
00074                       const char *nname, const char *pname)
00075 {
00076    static const char *brk[] = {"exec", "named", 0};
00077    char *val;
00078    int hostok;
00079 
00080 // Make sure that at least one thing appears after the if
00081 //
00082    if (!(val = Config.GetWord()))
00083       {if (eDest) eDest->Emsg("Config","Host name missing after 'if' in", what);
00084        return -1;
00085       }
00086 
00087 // Check if we are one of the listed hosts
00088 //
00089    if (!is1of(val, brk))
00090       {do {hostok = XrdNetDNS::isMatch(hname, val);
00091            val = Config.GetWord();
00092           } while(!hostok && val && !is1of(val, brk));
00093       if (hostok)
00094          { while(val && !is1of(val, brk)) val = Config.GetWord();
00095            // No more directives
00096            if (!val) return 1;
00097          } else return 0;
00098       }
00099 
00100 // Check if we need to compare program names (we are here only if we either
00101 // passed the hostlist test or there was no hostlist present)
00102 //
00103    if (!strcmp(val, "exec"))
00104       {if (!(val = Config.GetWord()) || !strcmp(val, "&&"))
00105           {if (eDest)
00106               eDest->Emsg("Config","Program name missing after 'if exec' in",what);
00107               return -1;
00108           }
00109 
00110        // Check if we are one of the programs.
00111        //
00112        if (!pname) return 0;
00113        while(val && strcmp(val, pname))
00114             if (!strcmp(val, "&&")) return 0;
00115                else  val = Config.GetWord();
00116        if (!val) return 0;
00117        while(val && strcmp(val, "&&")) val = Config.GetWord();
00118        if (!val) return 1;
00119 
00120        if (!(val = Config.GetWord()))
00121           {if (eDest)
00122               eDest->Emsg("Config","Keyword missing after '&&' in",what);
00123               return -1;
00124           }
00125        if (strcmp(val, "named"))
00126           {if (eDest)
00127               eDest->Emsg("Config",val,"is invalid after '&&' in",what);
00128               return -1;
00129           }
00130       }
00131 
00132 // Check if we need to compare net names (we are here only if we either
00133 // passed the hostlist test or there was no hostlist present)
00134 //
00135    if (!(val = Config.GetWord()))
00136       {if (eDest)
00137           eDest->Emsg("Config","Instance name missing after 'if named' in", what);
00138        return -1;
00139       }
00140 
00141 // Check if we are one of the names
00142 //
00143    if (!nname) return 0;
00144    while(val && strcmp(val, nname)) val = Config.GetWord();
00145 
00146 // All done
00147 //
00148    return (val != 0);
00149 }
00150 
00151 /******************************************************************************/
00152 /*                              f m t B y t e s                               */
00153 /******************************************************************************/
00154   
00155 int XrdOucUtils::fmtBytes(long long val, char *buff, int bsz)
00156 {
00157    static const long long Kval = 1024LL;
00158    static const long long Mval = 1024LL*1024LL;
00159    static const long long Gval = 1024LL*1024LL*1024LL;
00160    static const long long Tval = 1024LL*1024LL*1024LL*1024LL;
00161    char sName = ' ';
00162    int resid;
00163 
00164 // Get correct scaling
00165 //
00166         if (val < 1024)  return snprintf(buff, bsz, "%lld", val);
00167         if (val < Mval) {val = val*10/Kval; sName = 'K';}
00168    else if (val < Gval) {val = val*10/Mval; sName = 'M';}
00169    else if (val < Tval) {val = val*10/Gval; sName = 'G';}
00170    else                 {val = val*10/Tval; sName = 'T';}
00171    resid = val%10LL; val = val/10LL;
00172 
00173 // Format it
00174 //
00175    return snprintf(buff, bsz, "%lld.%d%c", val, resid, sName);
00176 }
00177 
00178 /******************************************************************************/
00179 /*                               g e n P a t h                                */
00180 /******************************************************************************/
00181 
00182 char *XrdOucUtils::genPath(const char *p_path, const char *inst, 
00183                            const char *s_path)
00184 {
00185    char buff[2048];
00186    int i = strlcpy(buff, p_path, sizeof(buff));
00187 
00188    if (buff[i-1] != '/') {buff[i++] = '/'; buff[i] = '\0';}
00189    if (inst) {strcpy(buff+i, inst); strcat(buff, "/");}
00190    if (s_path) strcat(buff, s_path);
00191 
00192    i = strlen(buff);
00193    if (buff[i-1] != '/') {buff[i++] = '/'; buff[i] = '\0';}
00194 
00195    return strdup(buff);
00196 }
00197 
00198 /******************************************************************************/
00199   
00200 int XrdOucUtils::genPath(char *buff, int blen, const char *path, const char *psfx)
00201 {
00202     int i, j;
00203 
00204     i = strlen(path);
00205     j = (psfx ? strlen(psfx) : 0);
00206     if (i+j+3 > blen) return -ENAMETOOLONG;
00207 
00208      strcpy(buff, path);
00209      if (psfx)
00210         {if (buff[i-1] != '/') buff[i++] = '/';
00211          strcpy(&buff[i], psfx);
00212          if (psfx[j-1] != '/') strcat(buff, "/");
00213         }
00214     return 0;
00215 }
00216 
00217 /******************************************************************************/
00218 /*                              I n s t N a m e                               */
00219 /******************************************************************************/
00220   
00221 const char *XrdOucUtils::InstName(int TranOpt)
00222 {
00223    const char *iName = getenv("XRDNAME");
00224 
00225 // If tran is zero, return what we have
00226 //
00227    if (!TranOpt) return iName;
00228 
00229 // If trans is positive then make sure iName has a value. Otherwise, make sure
00230 // iName has no value if it's actually "anon".
00231 //
00232    if (TranOpt > 0) {if (!iName || !*iName) iName = "anon";}
00233       else if (iName && !strcmp(iName, "anon")) iName = 0;
00234    return iName;
00235 }
00236 /******************************************************************************/
00237   
00238 const char *XrdOucUtils::InstName(const char *name, int Fillit)
00239 { return (Fillit ? name && *name                        ? name : "anon"
00240                  : name && strcmp(name,"anon") && *name ? name :     0);
00241 }
00242   
00243 /******************************************************************************/
00244 /*                                 i s 1 o f                                  */
00245 /******************************************************************************/
00246   
00247 int XrdOucUtils::is1of(char *val, const char **clist)
00248 {
00249    int i = 0;
00250    while(clist[i]) if (!strcmp(val, clist[i])) return 1;
00251                       else i++;
00252    return 0;
00253 }
00254 
00255 /******************************************************************************/
00256 /*                              m a k e H o m e                               */
00257 /******************************************************************************/
00258   
00259 void XrdOucUtils::makeHome(XrdSysError &eDest, const char *inst)
00260 {
00261    char buff[1024];
00262 
00263    if (!inst || !getcwd(buff, sizeof(buff))) return;
00264 
00265    strcat(buff, "/"); strcat(buff, inst);
00266    if (MAKEDIR(buff, pathMode) && errno != EEXIST)
00267       {eDest.Emsg("Config", errno, "create home directory", buff);
00268        return;
00269       }
00270 
00271    if (chdir(buff) < 0)
00272       eDest.Emsg("Config", errno, "chdir to home directory", buff);
00273 }
00274 
00275 /******************************************************************************/
00276 /*                              m a k e P a t h                               */
00277 /******************************************************************************/
00278   
00279 int XrdOucUtils::makePath(char *path, mode_t mode)
00280 {
00281     char *next_path = path+1;
00282     struct stat buf;
00283 
00284 // Typically, the path exists. So, do a quick check before launching into it
00285 //
00286    if (!stat(path, &buf)) return 0;
00287 
00288 // Start creating directories starting with the root
00289 //
00290    while((next_path = index(next_path, int('/'))))
00291         {*next_path = '\0';
00292          if (MAKEDIR(path, mode))
00293             if (errno != EEXIST) return -errno;
00294          *next_path = '/';
00295          next_path = next_path+1;
00296         }
00297 
00298 // All done
00299 //
00300    return 0;
00301 }
00302  
00303 /******************************************************************************/
00304 /*                              s u b L o g f n                               */
00305 /******************************************************************************/
00306   
00307 char *XrdOucUtils::subLogfn(XrdSysError &eDest, const char *inst, char *logfn)
00308 {
00309    const mode_t lfm = S_IRWXU|S_IRWXG|S_IROTH|S_IXOTH;
00310    char buff[2048], *sp;
00311    int rc;
00312 
00313    if (!inst || !*inst) return logfn;
00314    if (!(sp = rindex(logfn, '/'))) strcpy(buff, "./");
00315       else {*sp = '\0'; strcpy(buff, logfn); strcat(buff, "/");}
00316 
00317    strcat(buff, inst); strcat(buff, "/");
00318 
00319    if ((rc = XrdOucUtils::makePath(buff, lfm)))
00320       {eDest.Emsg("Config", rc, "create log file path", buff);
00321        return 0;
00322       }
00323 
00324    if (sp) {*sp = '/'; strcat(buff, sp+1);}
00325       else strcat(buff, logfn);
00326 
00327    free(logfn);
00328    return strdup(buff);
00329 }
00330 
00331 /******************************************************************************/
00332 /*                            U n d e r c o v e r                             */
00333 /******************************************************************************/
00334 #ifdef WIN32
00335 void XrdOucUtils::Undercover(XrdSysError &, int)
00336 {
00337 }
00338 #else
00339 void XrdOucUtils::Undercover(XrdSysError &eDest, int noLog)
00340 {
00341    static const int maxFiles = 256;
00342    pid_t mypid;
00343    int myfd;
00344 
00345 // Issue warning if there is no logfile attached
00346 //
00347    if (noLog) eDest.Emsg("Config", "Warning! No log file specified; "
00348                                    "backgrounding disables all logging!");
00349 
00350 // Fork so that we are not tied to a shell
00351 //
00352    if ((mypid = fork()) < 0)
00353       {eDest.Emsg("Config", errno, "fork process 1 for backgrounding");
00354        return;
00355       }
00356       else if (mypid) _exit(0);
00357 
00358 // Become the process group leader
00359 //
00360    if (setsid() < 0)
00361       {eDest.Emsg("Config", errno, "doing setsid() for backgrounding");
00362        return;
00363       }
00364 
00365 // Fork to that we are cannot get a controlling terminal
00366 //
00367    if ((mypid = fork()) < 0)
00368       {eDest.Emsg("Config", errno, "fork process 2 for backgrounding");
00369        return;
00370       }
00371       else if (mypid) _exit(0);
00372 
00373 // Switch stdin, stdout, and stderr to /dev/null (we can't use /dev/console
00374 // unless we are root which is unlikely).
00375 //
00376    if ((myfd = open("/dev/null", O_RDWR)) < 0)
00377       {eDest.Emsg("Config", errno, "open /dev/null for backgrounding");
00378        return;
00379       }
00380    dup2(myfd, 0); dup2(myfd, 1); dup2(myfd, 2);
00381 
00382 // Close any open file descriptors left open by the parent process
00383 //
00384   for (myfd = 3; myfd < maxFiles; myfd++) close(myfd);
00385 }
00386 #endif
00387 

Generated on Tue Jul 5 14:46:57 2011 for ROOT_528-00b_version by  doxygen 1.5.1