#ifndef __OOUC_STREAM__ #define __OOUC_STREAM__ /******************************************************************************/ /* */ /* X r d O u c S t r e a m . h h */ /* */ /* (c) 2004 by the Board of Trustees of the Leland Stanford, Jr., University */ /* Produced by Andrew Hanushevsky for Stanford University under contract */ /* DE-AC02-76-SFO0515 with the Deprtment of Energy */ /* */ /* This file is part of the XRootD software suite. */ /* */ /* XRootD is free software: you can redistribute it and/or modify it under */ /* the terms of the GNU Lesser General Public License as published by the */ /* Free Software Foundation, either version 3 of the License, or (at your */ /* option) any later version. */ /* */ /* XRootD is distributed in the hope that it will be useful, but WITHOUT */ /* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ /* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public */ /* License for more details. */ /* */ /* You should have received a copy of the GNU Lesser General Public License */ /* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */ /* COPYING (GPL license). If not, see . */ /* */ /* The copyright holder's institutional names and contributor's names may not */ /* be used to endorse or promote products derived from this software without */ /* specific prior written permission of the institution or contributor. */ /******************************************************************************/ #include #include #include #ifdef WIN32 #include "XrdSys/XrdWin32.hh" #endif #include "XrdSys/XrdSysError.hh" struct StreamInfo; class XrdOucEnv; class XrdOucString; class XrdOucTList; class XrdOucStream { public: // When creating a stream object, you may pass an optional error routing object. // If you do so, error messages will be writen via the error object. Otherwise, // errors will be returned quietly. // XrdOucStream(XrdSysError *erobj=0, const char *ifname=0, XrdOucEnv *anEnv=0, const char *Pfx=0); ~XrdOucStream() {Close(); if (myInst) free(myInst); if (varVal) delete [] varVal; if (llBuff) free(llBuff); } // Attach a file descriptor to an existing stream. Any curently associated // stream is closed and detached. An optional buffer size can be specified. // Zero is returned upon success, otherwise a -1 (use LastError to get rc). // int Attach(int FileDescriptor, int bsz=2047); int AttachIO(int infd, int outfd, int bsz=2047); // Close the current stream and release the associated buffer. // void Close(int hold=0); // Detach a file descriptor from a stream. This should be called prior to // close/delete when you are managing your own descriptors. Return the FD num. // int Detach() {int oldFD = FD; FD = FE = -1; return oldFD;} // Wait for an Exec() to finish and return the ending status. Use this // function only when you need to find out the ending status of the command. // int Drain(); // Display last valid line if variable substitution enabled. Fully formed // input lines are displayed if 'set -v' was encountered (only when using // the GetxxxWord() methods), // void Echo(); void Echo(bool capture); // Execute a command on a stream. Returns 0 upon success or -1 otherwise. // Use LastError() to get the actual error code. Subsequent Get() calls // will return the standard output of the executed command. If inrd=1 then // standardin is redirected so that subqseuent Put() calls write to the // process via standard in. When inrd=-1 then the current attached FD's are // used to redirect STDIN and STDOUT of the child process. Standard error // is handled as determined by the efd argument: // efd < 0 -> How to handle the current stderr file decriptor: // -1 The current stderr file decriptor is unchanged. // Output of only stdout is to be captured by this stream. // -2 Output of only stderr is to be captured by this stream. // -3 Output of stdout and stderr is to be captured by this stream. // efd = 0 -> The stderr file descriptor is set to the original logging FD // efd > 0 -> The stderr file descriptor is set to the value of efd. // int Exec(const char *, int inrd=0, int efd=0); int Exec( char **, int inrd=0, int efd=0); // Get the file descriptor number associated with a stream // int FDNum() {return FD;} int FENum() {return FE;} // Flush any remaining output queued on an output stream. // void Flush() {fsync(FD); if (FE != FD) fsync(FE);} // Get the next record from a stream. Return null upon eof or error. Use // LastError() to determine which condition occurred (an error code of 0 // indicates that end of file has been reached). Upon success, a pointer // to the next record is returned. The record is terminated by a null char. // char *GetLine(); // Get the next blank-delimited token in the record returned by Getline(). A // null pointer is returned if no more tokens remain. Each token is terminated // a null byte. Note that the record buffer is modified during processing. The // first form returns simply a token pointer. The second form returns a token // pointer and a pointer to the remainder of the line with no leading blanks. // The lowcase argument, if 1, converts all letters to lower case in the token. // RetToken() simply backups the token scanner one token. None of these // methods perform variable substitution (see GetxxxWord() below). // char *GetToken(int lowcase=0); char *GetToken(char **rest, int lowcase=0); void RetToken(); // Get the next word, ignoring any blank lines and comment lines (lines whose // first non-blank is a pound sign). Words are returned until logical end of // line is encountered at which time, a null is returned. A subsequent call // will return the next word on the next logical line. A physical line may be // continued by placing a back slash at it's end (i.e., last non-blank char). // GetFirstWord() always makes sure that the first word of a logical line is // returned (useful for start afresh after a mid-sentence error). GetRest() // places the remining tokens in the supplied buffer; returning 0 if the // buffer was too small. All of these methods perform variable substitution // should an XrdOucEnv object be passed to the constructor. // char *GetFirstWord(int lowcase=0); char *GetMyFirstWord(int lowcase=0); int GetRest(char *theBuf, int Blen, int lowcase=0); char *GetWord(int lowcase=0); // Indicate wether there is an active program attached to the stream // #ifndef WIN32 inline int isAlive() {return (child ? kill(child,0) == 0 : 0);} #else inline int isAlive() {return (child ? 1 : 0);} #endif // Return last error code encountered. // inline int LastError() {int n = ecode; ecode = 0; return n;} // Return the last input line // char *LastLine() {return recp;} // Suppress echoing the previous line when the next line is fetched. // int noEcho() {llBok = 0; return 0;} // Write a record to a stream, if a length is not given, then the buffer must // be null terminated and this defines the length (the null is not written). // int Put(const char *data, const int dlen); inline int Put(const char *data) {return Put(data, strlen(data));} // Write record fragments to a stream. The list of fragment/length pairs ends // when a null pointer is encountered. // int Put(const char *data[], const int dlen[]); // Insert a line into the stream buffer. This replaces anything that was there. // int PutLine(const char *data, int dlen=0); // Set the Env (returning the old Env). This is useful for suppressing // substitutions for a while. // XrdOucEnv *SetEnv(XrdOucEnv *newEnv) {XrdOucEnv *oldEnv = myEnv; myEnv = newEnv; return oldEnv;} // Set error routing // void SetEroute(XrdSysError *eroute) {Eroute = eroute;} // A 0 indicates that tabs in the stream should be converted to spaces. // A 1 inducates that tabs should be left alone (the default). // void Tabs(int x=1) {notabs = !x;} // Wait for inbound data to arrive. The argument is the max number of millisec // to wait (-1 means wait forever). Returns 0 if data is present. Otherwise, // -1 indicates that the connection timed out, a positive value indicates an // error and the value is the errno describing the error. // int Wait4Data(int msMax=-1); /******************************************************************************/ // The following methods are norally used only during initial configuration // to capture the actual configuration being used by each component. // Capture a message (typically informational before the start of file // processing); which is added as a comment. Pass a vector of string whose // last element is 0. // static void Capture(const char** cVec=0, bool linefeed=true); // Set the capture string object. A value of nil turns off capturing. The // current capture string pointer is returned. // static XrdOucString *Capture(XrdOucString *cfObj); // Return the current capture string object. // static XrdOucString *Capture(); /******************************************************************************/ private: void add2CFG(const char *data, bool isCMT=false); char *add2llB(char *tok, int reset=0); bool docont(); bool docont( const char *path, XrdOucTList *tlP); bool docontD(const char *path, XrdOucTList *tlP); bool docontF(const char *path, bool noentok=false); char *doelse(); char *doif(); bool Echo(int ec, const char *t1, const char *t2=0, const char *t3=0); int getValue(const char *path, char *vbuff, int vbsz); int isSet(char *var); char *vSubs(char *Var); int xMsg(const char *txt1, const char *txt2=0, const char *txt3=0); static const int maxVLen = 512; static const int llBsz = 1024; int FD; int FE; int bsize; int bleft; char *buff; char *bnext; char *recp; char *token; int flags; pid_t child; int ecode; int notabs; int xcont; int xline; char *myInst; StreamInfo *myInfo; // ABI compatible change! char *myRsv1; char *myRsv2; XrdSysError *Eroute; XrdOucEnv *myEnv; char *varVal; const char *llPrefix; char *llBuff; char *llBcur; int llBleft; char Verbose; char sawif; char skpel; char llBok; static XrdOucString *theCFG; }; #endif