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