00001
00002
00003
00004
00005
00006 #include <sys/types.h>
00007 #ifndef windows_platform
00008 #include <sys/wait.h>
00009 #else
00010 #include "Unix2Nt.h"
00011 #endif
00012 #include "execCmd.h"
00013 #include "objMetaOpr.h"
00014 #include "dataObjOpr.h"
00015 #include "miscServerFunct.h"
00016 #include "rodsLog.h"
00017 #include "rsGlobalExtern.h"
00018 #include "rcGlobalExtern.h"
00019
00020 #include "eirods_resource_backport.h"
00021 #include "eirods_resource_redirect.h"
00022
00023 #include <boost/thread/mutex.hpp>
00024 boost::mutex ExecCmdMutex;
00025 int initExecCmdMutex () {
00026 return (0);
00027 }
00028
00029 int
00030 rsExecCmd241 (rsComm_t *rsComm, execCmd241_t *execCmd241Inp,
00031 execCmdOut_t **execCmdOut)
00032 {
00033 execCmd_t execCmdInp;
00034 int status;
00035
00036 rstrcpy (execCmdInp.cmd, execCmd241Inp->cmd, LONG_NAME_LEN);
00037 rstrcpy (execCmdInp.cmdArgv, execCmd241Inp->cmdArgv, HUGE_NAME_LEN);
00038 rstrcpy (execCmdInp.execAddr, execCmd241Inp->execAddr, LONG_NAME_LEN);
00039 rstrcpy (execCmdInp.hintPath, execCmd241Inp->hintPath, LONG_NAME_LEN);
00040 execCmdInp.addPathToArgv = execCmd241Inp->addPathToArgv;
00041 execCmdInp.dummy = 0;
00042 bzero (&execCmdInp.condInput, sizeof (keyValPair_t));
00043
00044 status = rsExecCmd (rsComm, &execCmdInp, execCmdOut);
00045 return (status);
00046 }
00047
00048 int
00049 rsExecCmd (rsComm_t *rsComm, execCmd_t *execCmdInp, execCmdOut_t **execCmdOut)
00050 {
00051 int status;
00052 dataObjInfo_t *dataObjInfoHead = NULL;
00053 rodsServerHost_t *rodsServerHost;
00054 int remoteFlag;
00055 rodsHostAddr_t addr;
00056
00057
00058 if (strchr (execCmdInp->cmd, '/') != NULL) {
00059 rodsLog (LOG_ERROR,
00060 "rsExecCmd: bad cmd path %s", execCmdInp->cmd);
00061 return (BAD_EXEC_CMD_PATH);
00062 }
00063
00064 memset (&addr, 0, sizeof (addr));
00065 if (*execCmdInp->hintPath != '\0') {
00066 dataObjInp_t dataObjInp;
00067 memset (&dataObjInp, 0, sizeof (dataObjInp));
00068 rstrcpy (dataObjInp.objPath, execCmdInp->hintPath, MAX_NAME_LEN);
00069
00070
00071
00072 std::string resc_hier;
00073 char* resc_hier_ptr = getValByKey( &dataObjInp.condInput, RESC_HIER_STR_KW );
00074 if( resc_hier_ptr == NULL ) {
00075 eirods::error ret = eirods::resolve_resource_hierarchy( eirods::EIRODS_OPEN_OPERATION,
00076 rsComm, &dataObjInp, resc_hier );
00077 if( !ret.ok() ) {
00078 std::stringstream msg;
00079 msg << "failed in eirods::resolve_resource_hierarchy for [";
00080 msg << dataObjInp.objPath << "]";
00081 eirods::log( PASSMSG( msg.str(), ret ) );
00082 return ret.code();
00083 }
00084
00085
00086
00087
00088 addKeyVal( &dataObjInp.condInput, RESC_HIER_STR_KW, resc_hier.c_str() );
00089 addKeyVal( &execCmdInp->condInput, RESC_HIER_STR_KW, resc_hier.c_str() );
00090 } else {
00091 resc_hier = resc_hier_ptr;
00092
00093 }
00094
00095 status = getDataObjInfo (rsComm, &dataObjInp, &dataObjInfoHead,ACCESS_READ_OBJECT, 0 );
00096 if (status < 0) {
00097 rodsLog (LOG_ERROR,
00098 "rsExecCmd: getDataObjInfo error for hintPath %s",
00099 execCmdInp->hintPath);
00100 return (status);
00101 }
00102
00103 status = sortObjInfoForOpen (rsComm, &dataObjInfoHead, &execCmdInp->condInput, 0 );
00104
00105 if (status < 0 || NULL == dataObjInfoHead ) return status;
00106
00107 if (execCmdInp->addPathToArgv > 0) {
00108 char tmpArgv[LONG_NAME_LEN];
00109 rstrcpy (tmpArgv, execCmdInp->cmdArgv, HUGE_NAME_LEN);
00110 snprintf (execCmdInp->cmdArgv, HUGE_NAME_LEN, "%s %s",
00111 dataObjInfoHead->filePath, tmpArgv);
00112 }
00113
00114
00115
00116 std::string location;
00117 eirods::error ret = eirods::get_loc_for_hier_string( dataObjInfoHead->rescHier, location );
00118 if( !ret.ok() ) {
00119 eirods::log( PASSMSG( "rsGetHostForGet - failed in get_loc_for_hier_String", ret ) );
00120 return -1;
00121 }
00122
00123 rstrcpy (addr.zoneName, dataObjInfoHead->rescInfo->zoneName, NAME_LEN);
00124 rstrcpy (addr.hostAddr, location.c_str(), LONG_NAME_LEN );
00125
00126
00127 *execCmdInp->hintPath = '\0';
00128 rstrcpy (execCmdInp->execAddr, dataObjInfoHead->rescInfo->rescLoc,
00129 LONG_NAME_LEN);
00130 freeAllDataObjInfo (dataObjInfoHead);
00131 remoteFlag = resolveHost (&addr, &rodsServerHost);
00132 } else if (*execCmdInp->execAddr != '\0') {
00133 rstrcpy (addr.hostAddr, execCmdInp->execAddr, LONG_NAME_LEN);
00134 remoteFlag = resolveHost (&addr, &rodsServerHost);
00135 } else {
00136 rodsServerHost = LocalServerHost;
00137 remoteFlag = LOCAL_HOST;
00138 }
00139
00140 if (remoteFlag == LOCAL_HOST) {
00141 status = _rsExecCmd (rsComm, execCmdInp, execCmdOut);
00142 } else if (remoteFlag == REMOTE_HOST) {
00143 status = remoteExecCmd (rsComm, execCmdInp, execCmdOut,
00144 rodsServerHost);
00145 } else {
00146 rodsLog (LOG_NOTICE,
00147 "rsFileOpenByHost: resolveHost of %s error, status = %d",
00148 addr.hostAddr, remoteFlag);
00149 status = SYS_UNRECOGNIZED_REMOTE_FLAG;
00150 }
00151
00152 return (status);
00153 }
00154
00155 int
00156 remoteExecCmd (rsComm_t *rsComm, execCmd_t *execCmdInp,
00157 execCmdOut_t **execCmdOut, rodsServerHost_t *rodsServerHost)
00158 {
00159 int status;
00160
00161 if (rodsServerHost == NULL) {
00162 rodsLog (LOG_NOTICE,
00163 "remoteExecCmd: Invalid rodsServerHost");
00164 return SYS_INVALID_SERVER_HOST;
00165 }
00166
00167 if ((status = svrToSvrConnect (rsComm, rodsServerHost)) < 0) {
00168 return status;
00169 }
00170
00171 status = rcExecCmd (rodsServerHost->conn, execCmdInp, execCmdOut);
00172
00173 if (status < 0) {
00174 rodsLog (LOG_ERROR,
00175 "remoteExecCmd: rcExecCmd failed for %s. status = %d",
00176 execCmdInp->cmd, status);
00177 } else if (status > 0 &&
00178 getValByKey (&execCmdInp->condInput, STREAM_STDOUT_KW) != NULL) {
00179 int fileInx = status;
00180 (*execCmdOut)->status = bindStreamToIRods (rodsServerHost, fileInx);
00181 if ((*execCmdOut)->status < 0) {
00182 fileCloseInp_t remFileCloseInp;
00183 rodsLog (LOG_ERROR,
00184 "remoteExecCmd: bindStreamToIRods failed. status = %d",
00185 (*execCmdOut)->status);
00186 memset (&remFileCloseInp, 0, sizeof (remFileCloseInp));
00187 remFileCloseInp.fileInx = fileInx;
00188 rcFileClose (rodsServerHost->conn, &remFileCloseInp);
00189 }
00190 status = (*execCmdOut)->status;
00191 } else {
00192 status = 0;
00193 }
00194 return status;
00195 }
00196
00197 int
00198 _rsExecCmd (rsComm_t *rsComm, execCmd_t *execCmdInp, execCmdOut_t **execCmdOut)
00199 {
00200 int childPid;
00201 int stdoutFd[2];
00202 int stderrFd[2];
00203 int statusFd[2];
00204 execCmdOut_t *myExecCmdOut;
00205 bytesBuf_t statusBuf;
00206 int status, childStatus;
00207 #ifdef windows_platform
00208 int pipe_buf_size = META_STR_LEN;
00209 #endif
00210
00211 #ifndef windows_platform
00212 ExecCmdMutex.lock();
00213 if (pipe (stdoutFd) < 0)
00214 #else
00215 if(_pipe(stdoutFd, pipe_buf_size, O_BINARY) < 0)
00216 #endif
00217 {
00218 rodsLog (LOG_ERROR,
00219 "_rsExecCmd: pipe create failed. errno = %d", errno);
00220 return (SYS_PIPE_ERROR - errno);
00221 }
00222
00223 #ifndef windows_platform
00224 if (pipe (stderrFd) < 0)
00225 #else
00226 if(_pipe(stderrFd, pipe_buf_size, O_BINARY) < 0)
00227 #endif
00228 {
00229 rodsLog (LOG_ERROR,
00230 "_rsExecCmd: pipe create failed. errno = %d", errno);
00231 return (SYS_PIPE_ERROR - errno);
00232 }
00233
00234 #ifndef windows_platform
00235 if (pipe (statusFd) < 0)
00236 #else
00237 if(_pipe(statusFd, pipe_buf_size, O_BINARY) < 0)
00238 #endif
00239 {
00240 rodsLog (LOG_ERROR,
00241 "_rsExecCmd: pipe create failed. errno = %d", errno);
00242 return (SYS_PIPE_ERROR - errno);
00243 }
00244
00245 #ifndef windows_platform
00246
00247 childPid = fork ();
00248
00249 ExecCmdMutex.unlock();
00250 if (childPid == 0) {
00251 char *tmpStr;
00252
00253 if ((tmpStr = getValByKey (&execCmdInp->condInput, EXEC_CMD_RULE_KW))
00254 != NULL) {
00255 char *myStr = (char*)malloc (NAME_LEN + 20);
00256 snprintf (myStr, NAME_LEN + 20, "%s=%s", EXEC_CMD_RULE_KW, tmpStr);
00257 putenv(myStr);
00258
00259 }
00260 close (stdoutFd[0]);
00261 close (stderrFd[0]);
00262 close (statusFd[0]);
00263 status = execCmd (execCmdInp, stdoutFd[1], stderrFd[1]);
00264 if (status < 0) {
00265 status = EXEC_CMD_ERROR - errno;
00266 }
00267
00268 write (statusFd[1], &status, 4);
00269
00270 exit(1);
00271 } else if (childPid < 0) {
00272 rodsLog (LOG_ERROR,
00273 "_rsExecCmd: RODS_FORK failed. errno = %d", errno);
00274 return (SYS_FORK_ERROR);
00275 }
00276 #else
00277 status = execCmd (execCmdInp, stdoutFd[1], stderrFd[1]);
00278 if (status < 0) {
00279 status = EXEC_CMD_ERROR - errno;
00280 }
00281 if(status < 0)
00282 {
00283 rodsLog (LOG_ERROR, "_rsExecCmd: RODS_FORK failed. errno = %d", errno);
00284 return (SYS_FORK_ERROR);
00285 }
00286 #endif
00287
00288
00289
00290 #ifndef windows_platform
00291 close (stdoutFd[1]);
00292 close (stderrFd[1]);
00293 close (statusFd[1]);
00294 #endif
00295
00296
00297 myExecCmdOut = *execCmdOut = (execCmdOut_t*)malloc (sizeof (execCmdOut_t));
00298 memset (myExecCmdOut, 0, sizeof (execCmdOut_t));
00299
00300 readToByteBuf (stdoutFd[0], &myExecCmdOut->stdoutBuf);
00301 if (getValByKey (&execCmdInp->condInput, STREAM_STDOUT_KW) != NULL &&
00302 myExecCmdOut->stdoutBuf.len >= MAX_SZ_FOR_EXECMD_BUF) {
00303
00304
00305 close (stderrFd[0]);
00306 close (statusFd[0]);
00307 myExecCmdOut->status = bindStreamToIRods (LocalServerHost, stdoutFd[0]);
00308 if (myExecCmdOut->status < 0) {
00309 rodsLog (LOG_ERROR,
00310 "_rsExecCmd: bindStreamToIRods failed. status = %d",
00311 myExecCmdOut->status);
00312 close (stdoutFd[0]);
00313 }
00314 } else {
00315 close (stdoutFd[0]);
00316 readToByteBuf (stderrFd[0], &myExecCmdOut->stderrBuf);
00317 close (stderrFd[0]);
00318 memset (&statusBuf, 0, sizeof (statusBuf));
00319 readToByteBuf (statusFd[0], &statusBuf);
00320 close (statusFd[0]);
00321 if (statusBuf.len == sizeof (int) + 1) {
00322 myExecCmdOut->status = *((int *)statusBuf.buf);
00323 free (statusBuf.buf);
00324 }
00325 childStatus = 0;
00326
00327 #ifndef windows_platform
00328 status = waitpid (childPid, &childStatus, 0);
00329 if (status >= 0 && myExecCmdOut->status >= 0 && childStatus != 0) {
00330 rodsLog (LOG_ERROR,
00331 "_rsExecCmd: waitpid status = %d, myExecCmdOut->status = %d, childStatus = %d", status, myExecCmdOut->status, childStatus);
00332 myExecCmdOut->status = EXEC_CMD_ERROR;
00333 }
00334 #endif
00335 }
00336 return (myExecCmdOut->status);
00337 }
00338
00339 int
00340 execCmd (execCmd_t *execCmdInp, int stdOutFd, int stdErrFd)
00341 {
00342 char cmdPath[LONG_NAME_LEN];
00343 char *av[LONG_NAME_LEN];
00344 int status;
00345
00346 snprintf (cmdPath, LONG_NAME_LEN, "%s/%s", CMD_DIR, execCmdInp->cmd);
00347
00348 initCmdArg (av, execCmdInp->cmdArgv, cmdPath);
00349
00350 closeAllL1desc (ThisComm);
00351
00352 #ifndef windows_platform
00353
00354
00355 close (0);
00356 close (1);
00357 close (2);
00358
00359 dup2 (stdOutFd, 0);
00360 dup2 (stdOutFd, 1);
00361 dup2 (stdErrFd, 2);
00362 close (stdOutFd);
00363 close (stdErrFd);
00364
00365 status = execv (av[0], av);
00366
00367 #else
00368 status = _spawnv(_P_NOWAIT, av[0], av);
00369 #endif
00370
00371 return (status);
00372 }
00373
00374 int
00375 initCmdArg (char *av[], char *cmdArgv, char *cmdPath)
00376 {
00377 int avInx = 0, i;
00378 char *startPtr, *curPtr;
00379 int quoteCnt, curLen;
00380 char tmpCmdArgv[HUGE_NAME_LEN];
00381
00382 av[avInx] = strdup (cmdPath);
00383 avInx++;
00384
00385
00386
00387 if (strlen (cmdArgv) > 0) {
00388 rstrcpy (tmpCmdArgv, cmdArgv, HUGE_NAME_LEN);
00389 startPtr = curPtr = tmpCmdArgv;
00390 quoteCnt = curLen = 0;
00391 while (*curPtr != '\0') {
00392 if ((*curPtr == ' ' && quoteCnt == 0 && curLen > 0) ||
00393 quoteCnt == 2) {
00394
00395 *curPtr = '\0';
00396 curPtr++;
00397 av[avInx] = strdup (startPtr);
00398 avInx++;
00399 startPtr = curPtr;
00400 quoteCnt = curLen = 0;
00401 } else if (*curPtr == ' ' && quoteCnt <= 1 && curLen == 0) {
00402
00403 curPtr++;
00404 startPtr = curPtr;
00405
00406 } else if ( (*curPtr == '\'' || *curPtr == '\"')
00407 && (*(curPtr-1) == '\\') ) {
00408 curPtr++;
00409 curLen++;
00410
00411 } else if (*curPtr == '\'' || *curPtr == '\"') {
00412 quoteCnt++;
00413
00414 if (quoteCnt == 1) {
00415 curPtr++;
00416 startPtr = curPtr;
00417 }
00418 } else {
00419
00420 curPtr++;
00421 curLen++;
00422 }
00423 }
00424
00425 if (curLen > 0) {
00426 av[avInx] = strdup (startPtr);
00427 avInx++;
00428 }
00429 }
00430
00431
00432
00433 av[avInx] = NULL;
00434
00435
00436 for (i = 0; i < avInx ; i++) {
00437 curPtr = av[i];
00438 startPtr = curPtr;
00439 while (*curPtr != '\0') {
00440 if (*curPtr == '\\' && (*(curPtr+1) == '\'' || *(curPtr+1) == '\"')) {
00441 curPtr++;
00442 }
00443 *startPtr = *curPtr;
00444 curPtr++;
00445 startPtr++;
00446 }
00447 *startPtr = '\0';
00448 }
00449
00450
00451 return (0);
00452 }
00453