XrdOucProg.cc

Go to the documentation of this file.
00001 /******************************************************************************/
00002 /*                                                                            */
00003 /*                         X r d O u c P r o g . c c                          */
00004 /*                                                                            */
00005 /* (c) 2004 by the Board of Trustees of the Leland Stanford, Jr., University  */
00006 /*       All Rights Reserved. See XrdInfo.cc for complete License Terms       */
00007 /*   Produced by Andrew Hanushevsky for Stanford University under contract    */
00008 /*                DE-AC03-76-SFO0515 with the Deprtment of Energy             */
00009 /******************************************************************************/
00010 
00011 //          $Id: XrdOucProg.cc 32231 2010-02-05 18:24:46Z ganis $
00012 
00013 const char *XrdOucProgCVSID = "$Id: XrdOucProg.cc 32231 2010-02-05 18:24:46Z ganis $";
00014 
00015 #include <errno.h>
00016 #include <stdio.h>
00017 #include <string.h>
00018 #ifndef WIN32
00019 #include <unistd.h>
00020 #include <sys/types.h>
00021 #include <sys/wait.h>
00022 #else
00023 #include <sys/types.h>
00024 #include "XrdSys/XrdWin32.hh"
00025 #endif
00026 
00027 #include "XrdOuc/XrdOucProg.hh"
00028 #include "XrdOuc/XrdOucStream.hh"
00029 #include "XrdSys/XrdSysError.hh"
00030 #include "XrdSys/XrdSysPthread.hh"
00031 
00032 /******************************************************************************/
00033 /*                            D e s t r u c t o r                             */
00034 /******************************************************************************/
00035   
00036 XrdOucProg::~XrdOucProg()
00037 {
00038    if (ArgBuff) free(ArgBuff);
00039    if (myStream) delete myStream;
00040 }
00041 
00042 /******************************************************************************/
00043 /*                                  F e e d                                   */
00044 /******************************************************************************/
00045 
00046 int XrdOucProg::Feed(const char *data[], const int dlen[])
00047 {
00048    static XrdSysMutex feedMutex;
00049    XrdSysMutexHelper  feedHelper;
00050    int rc;
00051 
00052 // Make sure we have a stream
00053 //
00054    if (!myStream) return EPIPE;
00055    feedHelper.Lock(&feedMutex);
00056 
00057 // Check if this command is still running
00058 //
00059    if (!myStream->isAlive() && !Restart())
00060       {if (eDest) eDest->Emsg("Prog" "Unable to restart", Arg[0]);
00061         return EPIPE;
00062       }
00063 
00064 // Send the line to the program
00065 //
00066    if (!myStream->Put((const char **)data, (const int *)dlen)) return 0;
00067    if (eDest) 
00068       eDest->Emsg("Prog", myStream->LastError(), "feed", Arg[0]);
00069    if ((rc = Restart()))
00070       {if (eDest) eDest->Emsg("Prog", rc, "restart", Arg[0]);
00071        return EPIPE;
00072       }
00073    if (!myStream->Put((const char **)data, (const int *)dlen)) return 0;
00074    if (eDest) 
00075       eDest->Emsg("Prog", myStream->LastError(), "refeed", Arg[0]);
00076    return EPIPE;
00077 }
00078   
00079 /******************************************************************************/
00080 /*                                   R u n                                    */
00081 /******************************************************************************/
00082   
00083 int XrdOucProg::Run(XrdOucStream *Sp, const char *arg1, const char *arg2,
00084                                       const char *arg3, const char *arg4)
00085 {
00086    const int maxArgs = sizeof(Arg)/sizeof(Arg[0])+4;
00087    char *myArgs[maxArgs+1];
00088    int rc, j = numArgs;
00089 
00090 // If we have no program, return an error
00091 //
00092    if (!ArgBuff) 
00093       {if (eDest) eDest->Emsg("Run", "No program specified");
00094        return -ENOEXEC;
00095       }
00096 
00097 // Copy the arglist to our private area
00098 //
00099    memcpy((void *)myArgs, (const void *)Arg, lenArgs);
00100 
00101 // Append additional arguments as needed
00102 //
00103    if (arg1 && j < maxArgs) myArgs[j++] = (char *)arg1;
00104    if (arg2 && j < maxArgs) myArgs[j++] = (char *)arg2;
00105    if (arg3 && j < maxArgs) myArgs[j++] = (char *)arg3;
00106    if (arg4 && j < maxArgs) myArgs[j++] = (char *)arg4;
00107 
00108 // Make sure we don't have too many
00109 //
00110    if (j >= maxArgs) 
00111       {if (eDest) eDest->Emsg("Run", E2BIG, "execute", Arg[0]);
00112        return -E2BIG;
00113       }
00114    myArgs[j] = (char *)0;
00115 
00116 // Execute the command
00117 //
00118    if (Sp->Exec(myArgs, 1, theEFD))
00119       {rc = Sp->LastError();
00120        if (eDest) eDest->Emsg("Run", rc, "execute", Arg[0]);
00121        return -rc;
00122       }
00123 
00124 // All done, caller will drain output
00125 //
00126    return 0;
00127 }
00128 
00129 /******************************************************************************/
00130 
00131 int XrdOucProg::Run(const char *arg1, const char *arg2,
00132                     const char *arg3, const char *arg4)
00133 {
00134    XrdOucStream cmd;
00135    char *lp;
00136    int rc;
00137 
00138 // Execute the command
00139 //
00140    if ((rc = Run(&cmd, arg1, arg2, arg3, arg4))) return rc;
00141 
00142 // Drain all output
00143 //
00144    while((lp = cmd.GetLine()))
00145         if (eDest && *lp) eDest->Emsg("Run", lp);
00146 
00147 // Drain the command
00148 //
00149    rc = cmd.Drain();
00150 
00151 // Determine ending status
00152 //
00153    if (WIFSIGNALED(rc))
00154       {if (eDest)
00155           {char buff[16];
00156            sprintf(buff, "%d", WTERMSIG(rc));
00157            eDest->Emsg("Run", Arg[0], "killed by signal", buff);
00158           }
00159        return -EPIPE;
00160       }
00161    if (WIFEXITED(rc))
00162       {rc = WEXITSTATUS(rc);
00163        if (rc && eDest) 
00164           {char buff[16];
00165            sprintf(buff, "%d", rc);
00166            eDest->Emsg("Run", Arg[0], "ended with status", buff);
00167           }
00168        return -rc;
00169       }
00170    return 0; // We'll assume all went well here
00171 }
00172 
00173 /******************************************************************************/
00174 /*                                 S e t u p                                  */
00175 /******************************************************************************/
00176   
00177 int XrdOucProg::Setup(const char *prog, XrdSysError *errP)
00178 {
00179    const int maxArgs = sizeof(Arg)/sizeof(Arg[0]);
00180    char *pp;
00181    int j;
00182 
00183 // Prepare to handle the program
00184 //
00185    if (ArgBuff) free(ArgBuff);
00186    pp = ArgBuff = strdup(prog);
00187    if (!errP) errP = eDest;
00188   
00189 // Construct the argv array based on passed command line.
00190 //
00191 for (j = 0; j < maxArgs-1 && *pp; j++)
00192     {while(*pp == ' ') pp++;
00193      if (!(*pp)) break;
00194      Arg[j] = pp;
00195      while(*pp && *pp != ' ') pp++;
00196      if (*pp) {*pp = '\0'; pp++;}
00197     }
00198 
00199 // Make sure we did not overflow the buffer
00200 //
00201    if (j == maxArgs-1 && *pp) 
00202       {if (errP) errP->Emsg("Run", E2BIG, "set up", Arg[0]);
00203        free(ArgBuff); ArgBuff = 0;
00204        return -E2BIG;
00205       }
00206    Arg[j] = (char *)0;
00207    numArgs= j;
00208    lenArgs = sizeof(Arg[0]) * numArgs;
00209 
00210 // Make sure the program is really executable
00211 //
00212    if (access(Arg[0], X_OK))
00213       {int rc = errno;
00214        if (errP) errP->Emsg("Run", rc, "set up", Arg[0]);
00215        free(ArgBuff); ArgBuff = 0;
00216        return rc;
00217       }
00218    return 0;
00219 }
00220  
00221 /******************************************************************************/
00222 /*                                 S t a r t                                  */
00223 /******************************************************************************/
00224   
00225 int XrdOucProg::Start()
00226 {
00227 
00228 // Create a stream for this command (it is an eror if we are already started)
00229 //
00230    if (myStream) return EBUSY;
00231    if (!(myStream = new XrdOucStream(eDest))) return ENOMEM;
00232 
00233 // Execute the command and let it linger
00234 //
00235    theEFD = 0;
00236    return Run(myStream);
00237 }
00238  
00239 /******************************************************************************/
00240 /*                       P r i v a t e   M e t h o d s                        */
00241 /******************************************************************************/
00242 /******************************************************************************/
00243 /*                               R e s t a r t                                */
00244 /******************************************************************************/
00245   
00246 int XrdOucProg::Restart()
00247 {
00248    myStream->Close();
00249    return Run(myStream);
00250 }

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