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