00001 #ifndef __OOUC_STREAM__ 00002 #define __OOUC_STREAM__ 00003 /******************************************************************************/ 00004 /* */ 00005 /* X r d O u c S t r e a m . h h */ 00006 /* */ 00007 /* (c) 2004 by the Board of Trustees of the Leland Stanford, Jr., University */ 00008 /* Produced by Andrew Hanushevsky for Stanford University under contract */ 00009 /* DE-AC02-76-SFO0515 with the Deprtment of Energy */ 00010 /* */ 00011 /* This file is part of the XRootD software suite. */ 00012 /* */ 00013 /* XRootD is free software: you can redistribute it and/or modify it under */ 00014 /* the terms of the GNU Lesser General Public License as published by the */ 00015 /* Free Software Foundation, either version 3 of the License, or (at your */ 00016 /* option) any later version. */ 00017 /* */ 00018 /* XRootD is distributed in the hope that it will be useful, but WITHOUT */ 00019 /* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ 00020 /* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public */ 00021 /* License for more details. */ 00022 /* */ 00023 /* You should have received a copy of the GNU Lesser General Public License */ 00024 /* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */ 00025 /* COPYING (GPL license). If not, see <http://www.gnu.org/licenses/>. */ 00026 /* */ 00027 /* The copyright holder's institutional names and contributor's names may not */ 00028 /* be used to endorse or promote products derived from this software without */ 00029 /* specific prior written permission of the institution or contributor. */ 00030 /******************************************************************************/ 00031 00032 #include <sys/types.h> 00033 #include <signal.h> 00034 #include <stdlib.h> 00035 #ifdef WIN32 00036 #include "XrdSys/XrdWin32.hh" 00037 #endif 00038 00039 #include "XrdSys/XrdSysError.hh" 00040 00041 struct StreamInfo; 00042 class XrdOucEnv; 00043 class XrdOucTList; 00044 00045 class XrdOucStream 00046 { 00047 public: 00048 00049 // When creating a stream object, you may pass an optional error routing object. 00050 // If you do so, error messages will be writen via the error object. Otherwise, 00051 // errors will be returned quietly. 00052 // 00053 XrdOucStream(XrdSysError *erobj=0, const char *ifname=0, 00054 XrdOucEnv *anEnv=0, const char *Pfx=0); 00055 00056 ~XrdOucStream() {Close(); if (myInst) free(myInst); 00057 if (varVal) delete [] varVal; 00058 if (llBuff) free(llBuff); 00059 } 00060 00061 // Attach a file descriptor to an existing stream. Any curently associated 00062 // stream is closed and detached. An optional buffer size can be specified. 00063 // Zero is returned upon success, otherwise a -1 (use LastError to get rc). 00064 // 00065 int Attach(int FileDescriptor, int bsz=2047); 00066 int AttachIO(int infd, int outfd, int bsz=2047); 00067 00068 // Close the current stream and release the associated buffer. 00069 // 00070 void Close(int hold=0); 00071 00072 // Detach a file descriptor from a stream. This should be called prior to 00073 // close/delete when you are managing your own descriptors. Return the FD num. 00074 // 00075 int Detach() {int oldFD = FD; FD = FE = -1; return oldFD;} 00076 00077 // Wait for an Exec() to finish and return the ending status. Use this 00078 // function only when you need to find out the ending status of the command. 00079 // 00080 int Drain(); 00081 00082 // Display last valid line if variable substitution enabled. Fully formed 00083 // input lines are displayed if 'set -v' was encountered (only when using 00084 // the GetxxxWord() methods), 00085 // 00086 void Echo(); 00087 00088 // Execute a command on a stream. Returns 0 upon success or -1 otherwise. 00089 // Use LastError() to get the actual error code. Subsequent Get() calls 00090 // will return the standard output of the executed command. If inrd=1 then 00091 // standardin is redirected so that subqseuent Put() calls write to the 00092 // process via standard in. When inrd=-1 then the current attached FD's are 00093 // used to redirect STDIN and STDOUT of the child process. Standard error 00094 // is handled as determined by the efd argument: 00095 // efd < 0 -> How to handle the current stderr file decriptor: 00096 // -1 The current stderr file decriptor is unchanged. 00097 // Output of only stdout is to be captured by this stream. 00098 // -2 Output of only stderr is to be captured by this stream. 00099 // -3 Output of stdout and stderr is to be captured by this stream. 00100 // efd = 0 -> The stderr file descriptor is set to the original logging FD 00101 // efd > 0 -> The stderr file descriptor is set to the value of efd. 00102 // 00103 int Exec(const char *, int inrd=0, int efd=0); 00104 int Exec( char **, int inrd=0, int efd=0); 00105 00106 // Get the file descriptor number associated with a stream 00107 // 00108 int FDNum() {return FD;} 00109 int FENum() {return FE;} 00110 00111 // Flush any remaining output queued on an output stream. 00112 // 00113 void Flush() {fsync(FD); if (FE != FD) fsync(FE);} 00114 00115 // Get the next record from a stream. Return null upon eof or error. Use 00116 // LastError() to determine which condition occurred (an error code of 0 00117 // indicates that end of file has been reached). Upon success, a pointer 00118 // to the next record is returned. The record is terminated by a null char. 00119 // 00120 char *GetLine(); 00121 00122 // Get the next blank-delimited token in the record returned by Getline(). A 00123 // null pointer is returned if no more tokens remain. Each token is terminated 00124 // a null byte. Note that the record buffer is modified during processing. The 00125 // first form returns simply a token pointer. The second form returns a token 00126 // pointer and a pointer to the remainder of the line with no leading blanks. 00127 // The lowcase argument, if 1, converts all letters to lower case in the token. 00128 // RetToken() simply backups the token scanner one token. None of these 00129 // methods perform variable substitution (see GetxxxWord() below). 00130 // 00131 char *GetToken(int lowcase=0); 00132 char *GetToken(char **rest, int lowcase=0); 00133 void RetToken(); 00134 00135 // Get the next word, ignoring any blank lines and comment lines (lines whose 00136 // first non-blank is a pound sign). Words are returned until logical end of 00137 // line is encountered at which time, a null is returned. A subsequent call 00138 // will return the next word on the next logical line. A physical line may be 00139 // continued by placing a back slash at it's end (i.e., last non-blank char). 00140 // GetFirstWord() always makes sure that the first word of a logical line is 00141 // returned (useful for start afresh after a mid-sentence error). GetRest() 00142 // places the remining tokens in the supplied buffer; returning 0 if the 00143 // buffer was too small. All of these methods perform variable substitution 00144 // should an XrdOucEnv object be passed to the constructor. 00145 // 00146 char *GetFirstWord(int lowcase=0); 00147 char *GetMyFirstWord(int lowcase=0); 00148 int GetRest(char *theBuf, int Blen, int lowcase=0); 00149 char *GetWord(int lowcase=0); 00150 00151 // Indicate wether there is an active program attached to the stream 00152 // 00153 #ifndef WIN32 00154 inline int isAlive() {return (child ? kill(child,0) == 0 : 0);} 00155 #else 00156 inline int isAlive() {return (child ? 1 : 0);} 00157 #endif 00158 00159 // Return last error code encountered. 00160 // 00161 inline int LastError() {int n = ecode; ecode = 0; return n;} 00162 00163 // Return the last input line 00164 // 00165 char *LastLine() {return recp;} 00166 00167 // Suppress echoing the previous line when the next line is fetched. 00168 // 00169 int noEcho() {llBok = 0; return 0;} 00170 00171 // Write a record to a stream, if a length is not given, then the buffer must 00172 // be null terminated and this defines the length (the null is not written). 00173 // 00174 int Put(const char *data, const int dlen); 00175 inline int Put(const char *data) {return Put(data, strlen(data));} 00176 00177 // Write record fragments to a stream. The list of fragment/length pairs ends 00178 // when a null pointer is encountered. 00179 // 00180 int Put(const char *data[], const int dlen[]); 00181 00182 // Insert a line into the stream buffer. This replaces anything that was there. 00183 // 00184 int PutLine(const char *data, int dlen=0); 00185 00186 // Set the Env (returning the old Env). This is useful for suppressing 00187 // substitutions for a while. 00188 // 00189 XrdOucEnv *SetEnv(XrdOucEnv *newEnv) 00190 {XrdOucEnv *oldEnv = myEnv; myEnv = newEnv; return oldEnv;} 00191 00192 // Set error routing 00193 // 00194 void SetEroute(XrdSysError *eroute) {Eroute = eroute;} 00195 00196 // A 0 indicates that tabs in the stream should be converted to spaces. 00197 // A 1 inducates that tabs should be left alone (the default). 00198 // 00199 void Tabs(int x=1) {notabs = !x;} 00200 00201 // Wait for inbound data to arrive. The argument is the max number of millisec 00202 // to wait (-1 means wait forever). Returns 0 if data is present. Otherwise, 00203 // -1 indicates that the connection timed out, a positive value indicates an 00204 // error and the value is the errno describing the error. 00205 // 00206 int Wait4Data(int msMax=-1); 00207 00208 /******************************************************************************/ 00209 00210 private: 00211 char *add2llB(char *tok, int reset=0); 00212 bool docont(); 00213 bool docont( const char *path, XrdOucTList *tlP); 00214 bool docontD(const char *path, XrdOucTList *tlP); 00215 bool docontF(const char *path, bool noentok=false); 00216 char *doelse(); 00217 char *doif(); 00218 bool Echo(int ec, const char *t1, const char *t2=0, const char *t3=0); 00219 int isSet(char *var); 00220 char *vSubs(char *Var); 00221 int xMsg(const char *txt1, const char *txt2=0, const char *txt3=0); 00222 00223 static const int maxVLen = 512; 00224 static const int llBsz = 1024; 00225 00226 int FD; 00227 int FE; 00228 int bsize; 00229 int bleft; 00230 char *buff; 00231 char *bnext; 00232 char *recp; 00233 char *token; 00234 int flags; 00235 pid_t child; 00236 int ecode; 00237 int notabs; 00238 int xcont; 00239 int xline; 00240 char *myInst; 00241 StreamInfo *myInfo; // ABI compatible change! 00242 char *myRsv1; 00243 char *myRsv2; 00244 XrdSysError *Eroute; 00245 XrdOucEnv *myEnv; 00246 char *varVal; 00247 const char *llPrefix; 00248 char *llBuff; 00249 char *llBcur; 00250 int llBleft; 00251 char Verbose; 00252 char sawif; 00253 char skpel; 00254 char llBok; 00255 }; 00256 #endif