Changeset 6623 for trunk/tools


Ignore:
Timestamp:
Sep 2, 2001, 12:48:10 AM (24 years ago)
Author:
bird
Message:

Don't use CMD.EXE unless needed. Cache PATH search results.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/tools/CmdQd/CmdQd.c

    r6543 r6623  
    1 /* $Id: CmdQd.c,v 1.2 2001-08-16 04:27:44 bird Exp $
     1/* $Id: CmdQd.c,v 1.3 2001-09-01 22:48:10 bird Exp $
    22 *
    33 * Command Queue Daemon / Client.
     
    193193
    194194
     195typedef struct PathCache
     196{
     197    char    szPath[4096 - CCHMAXPATH * 3]; /* The path which this is valid for. */
     198    char    szCurDir[CCHMAXPATH];       /* The current dir this is valid for. */
     199    char    szProgram[CCHMAXPATH];      /* The program. */
     200    char    szResult[CCHMAXPATH];       /* The result. */
     201} PATHCACHE, *PPATHCACHE;
     202
     203
    195204/*******************************************************************************
    196205*   Global Variables                                                           *
     
    227236void signalhandler(int sig);
    228237void Worker(void * iWorkerId);
     238char*WorkerArguments(char *pszArg, const char *pszzEnv, const char *pszCommand, char *pszCurDir, PPATHCACHE pPathCache);
     239char*fileNormalize(char *pszFilename, char *pszCurDir);
     240APIRET fileExist(const char *pszFilename);
    229241int  Submit(int rcIgnore);
    230242int  Wait(void);
     
    311323    }
    312324
    313     return 0;
     325    //return 0;
    314326}
    315327
     
    699711void signalhandler(int sig)
    700712{
    701      shrmemFree();
    702      exit(-42);
     713    sig = sig;
     714    shrmemFree();
     715    exit(-42);
    703716}
    704717
     
    711724void Worker(void * iWorkerId)
    712725{
     726    PATHCACHE   PathCache;
     727    memset(&PathCache, 0, sizeof(PathCache));
     728
    713729    while (!DosWaitEventSem(hevJobQueue, SEM_INDEFINITE_WAIT))
    714730    {
     
    758774             * Redirect output and start process.
    759775             */
    760             sprintf(szArg, "%s\t /C \"%s\"\n", getenv("COMSPEC"), pJob->JobInfo.szCommand);
    761             *strchr(szArg, '\t') = '\0';
     776            WorkerArguments(szArg, &pJob->JobInfo.szzEnv, &pJob->JobInfo.szCommand[0],
     777                            &pJob->JobInfo.szCurrentDir[0], &PathCache);
    762778            rc = DosCreatePipe(&hPipeR, &hPipeW, sizeof(pJobOutput->szOutput) - 1);
    763779            if (rc)
     
    912928        }
    913929    }
     930    iWorkerId = iWorkerId;
     931}
     932
     933
     934/**
     935 * Builds the input to DosExecPgm.
     936 * Will execute programs directly and command thru the shell.
     937 *
     938 * @returns pszArg.
     939 * @param   pszArg          Arguments to DosExecPgm.(output)
     940 *                          Assumes that the buffer is large enought.
     941 * @param   pszzEnv         Pointer to environment block.
     942 * @param   pszCommand      Command to execute.
     943 * @param   pszCurDir       From where the command is to executed.
     944 * @param   pPathCache      Used to cache the last path, executable, and the search result.
     945 */
     946char *WorkerArguments(char *pszArg, const char *pszzEnv, const char *pszCommand, char *pszCurDir, PPATHCACHE pPathCache)
     947{
     948    BOOL        fCMD = FALSE;
     949    const char *psz;
     950    const char *psz2;
     951    char *      pszW;
     952    char        ch;
     953    int         cch;
     954    APIRET      rc;
     955
     956    /*
     957     * Check if this is multiple command separated by either &, && or |.
     958     * Currently ignoring quotes for this test.
     959     */
     960    if (    strchr(pszCommand, '&')
     961        ||  strchr(pszCommand, '|'))
     962    {
     963        strcpy(pszArg, "cmd.exe");      /* doesn't use comspec, just defaults to cmd.exe in all cases. */
     964        fCMD = TRUE;
     965        psz2 = pszCommand;              /* start of arguments. */
     966    }
     967    else
     968    {
     969        char chEnd = ' ';
     970
     971        /*
     972         * Parse out the first name.
     973         */
     974        for (psz = pszCommand; *psz == '\t' || *psz == ' ';) //strip(,'L');
     975            psz++;
     976        if (*psz == '"' || *psz == '\'')
     977            chEnd = *psz++;
     978        psz2 = psz;
     979        if (chEnd == ' ')
     980        {
     981            while ((ch = *psz) != '\0' && ch != ' ' && ch != '\t')
     982                psz++;
     983        }
     984        else
     985        {
     986            while ((ch = *psz) != '\0' && ch != chEnd)
     987                psz++;
     988        }
     989        *pszArg = '\0';
     990        strncat(pszArg, psz2, psz - psz2);
     991        psz2 = psz+1;                   /* start of arguments. */
     992    }
     993
     994
     995    /*
     996     * Resolve the executable name if not qualified.
     997     * NB! We doesn't fully support references to other driveletters yet. (TODO/BUGBUG)
     998     */
     999    /* correct slashes */
     1000    pszW = pszArg;
     1001    while ((pszW = strchr(pszW, '//')) != NULL)
     1002        *pszW++ = '\\';
     1003
     1004    /* make sure it ends with .exe */
     1005    pszW = pszArg + strlen(pszArg) - 1;
     1006    while (pszW > pszArg && *pszW != '.' && *pszW != '\\')
     1007        pszW--;
     1008    if (*pszW != '.')
     1009        strcat(pszArg, ".exe");
     1010
     1011    if (pszArg[1] != ':' || *pszArg == *pszCurDir)
     1012    {
     1013        rc = -1;                        /* indicate that we've not found the file. */
     1014
     1015        /* relative path? - expand it */
     1016        if (strchr(pszArg, '\\') || pszArg[1] == ':')
     1017        {   /* relative path - expand it and check for file existence */
     1018            fileNormalize(pszArg, pszCurDir);
     1019            rc = fileExist(pszArg);
     1020        }
     1021        else
     1022        {   /* Search path. */
     1023            const char *pszPath = pszzEnv;
     1024            while (*pszPath != '\0' && strncmp(pszPath, "PATH=", 5))
     1025                pszPath += strlen(pszPath) + 1;
     1026
     1027            if (pszPath && *pszPath != '\0')
     1028            {
     1029                /* check cache */
     1030                if (   !strcmp(pPathCache->szProgram, pszArg)
     1031                    && !strcmp(pPathCache->szPath, pszPath)
     1032                    && !strcmp(pPathCache->szCurDir, pszCurDir)
     1033                       )
     1034                {
     1035                    strcpy(pszArg, pPathCache->szResult);
     1036                    rc = fileExist(pszArg);
     1037                }
     1038
     1039                if (rc)
     1040                {   /* search path */
     1041                    char    szResult[CCHMAXPATH];
     1042                    rc = DosSearchPath(SEARCH_IGNORENETERRS, pszPath, pszArg, &szResult[0] , sizeof(szResult));
     1043                    if (!rc)
     1044                    {
     1045                        strcpy(pszArg, szResult);
     1046
     1047                        /* update cache */
     1048                        strcpy(pPathCache->szProgram, pszArg);
     1049                        strcpy(pPathCache->szPath, pszPath);
     1050                        strcpy(pPathCache->szCurDir, pszCurDir);
     1051                        strcpy(pPathCache->szResult, szResult);
     1052                    }
     1053                }
     1054            }
     1055        }
     1056    }
     1057    /* else nothing to do - assume full path (btw. we don't have the current dir for other drives anyway :-) */
     1058    else
     1059        rc = !fCMD ? fileExist(pszArg) : NO_ERROR;
     1060
     1061    /* In case of error use CMD */
     1062    if (rc && !fCMD)
     1063    {
     1064        strcpy(pszArg, "cmd.exe");      /* doesn't use comspec, just defaults to cmd.exe in all cases. */
     1065        fCMD = TRUE;
     1066        psz2 = pszCommand;              /* start of arguments. */
     1067    }
     1068
     1069
     1070    /*
     1071     * Complete the argument string.
     1072     * ---
     1073     * szArg current holds the command.
     1074     * psz2 points to the first parameter. (needs strip(,'L'))
     1075     */
     1076    while ((ch = *psz2) != '\0' && (ch == '\t' || ch == ' '))
     1077        psz2++;
     1078
     1079    pszW = pszArg + strlen(pszArg) + 1;
     1080    cch = strlen(psz2);
     1081    if (!fCMD)
     1082    {
     1083        memcpy(pszW, psz2, ++cch);
     1084        pszW[cch] = '\0';
     1085    }
     1086    else
     1087    {
     1088        strcpy(pszW, "/C \"");
     1089        pszW += strlen(pszW);
     1090        memcpy(pszW, psz2, cch);
     1091        memcpy(pszW + cch, "\"\0", 3);
     1092    }
     1093
     1094    return pszArg;
     1095}
     1096
     1097
     1098
     1099/**
     1100 * Normalizes the path slashes for the filename. It will partially expand paths too.
     1101 * @returns pszFilename
     1102 * @param   pszFilename  Pointer to filename string. Not empty string!
     1103 *                       Much space to play with.
     1104 * @remark  (From fastdep.)
     1105 */
     1106char *fileNormalize(char *pszFilename, char *pszCurDir)
     1107{
     1108    char *  psz;
     1109    int     aiSlashes[CCHMAXPATH/2];
     1110    int     cSlashes;
     1111    int     i;
     1112
     1113    /*
     1114     * Init stuff.
     1115     */
     1116    for (i = 1, cSlashes; pszCurDir[i] != '\0'; i++)
     1117    {
     1118        if (pszCurDir[i] == '/')
     1119            pszCurDir[i] = '\\';
     1120        if (pszCurDir[i] == '\\')
     1121            aiSlashes[cSlashes++] = i;
     1122    }
     1123    if (pszCurDir[i-1] != '\\')
     1124    {
     1125        aiSlashes[cSlashes] = i;
     1126        pszCurDir[i++] = '\\';
     1127        pszCurDir[i] = '\0';
     1128    }
     1129
     1130
     1131    /* expand path? */
     1132    pszFilename = psz;
     1133    if (pszFilename[1] != ':')
     1134    {   /* relative path */
     1135        int     iSlash;
     1136        char    szFile[CCHMAXPATH];
     1137        char *  psz = szFile;
     1138
     1139        strcpy(szFile, pszFilename);
     1140        iSlash = *psz == '\\' ? 1 : cSlashes;
     1141        while (*psz != '\0')
     1142        {
     1143            if (*psz == '.' && psz[1] == '.'  && psz[2] == '\\')
     1144            {   /* up one directory */
     1145                if (iSlash > 0)
     1146                    iSlash--;
     1147                psz += 3;
     1148            }
     1149            else if (*psz == '.' && psz[1] == '\\')
     1150            {   /* no change */
     1151                psz += 2;
     1152            }
     1153            else
     1154            {   /* completed expantion! */
     1155                strncpy(pszFilename, pszCurDir, aiSlashes[iSlash]+1);
     1156                strcpy(pszFilename + aiSlashes[iSlash]+1, psz);
     1157                break;
     1158            }
     1159        }
     1160    }
     1161    /* else: assume full path */
     1162
     1163    return psz;
     1164}
     1165
     1166/**
     1167 * Checks if a given file exist.
     1168 * @returns 0 if the file exists.   (NO_ERROR)
     1169 *          2 if the file doesn't exist. (ERROR_FILE_NOT_FOUND)
     1170 * @param   pszFilename     Name of the file to check existance for.
     1171 */
     1172APIRET fileExist(const char *pszFilename)
     1173{
     1174    FILESTATUS3     fsts3;
     1175    return DosQueryPathInfo(pszFilename, FIL_STANDARD, &fsts3, sizeof(fsts3));
    9141176}
    9151177
     
    9231185int Submit(int rcIgnore)
    9241186{
    925     int     i;
    9261187    int     cch;
    9271188    int     rc;
     
    9601221        shrmemFree();
    9611222        return -1;
     1223    }
     1224    if (*psz == '"' && psz[cch-2] == '"')    /* remove start & end quotes if any */
     1225    {
     1226        cch--;
     1227        psz++;
    9621228    }
    9631229    memcpy(&pShrMem->u1.Submit.szCommand[0], psz, cch);
     
    10811347{
    10821348    int rc;
    1083     rc = DosAllocSharedMem((PPVOID)&pShrMem,
     1349    rc = DosAllocSharedMem((PPVOID)(PVOID)&pShrMem,
    10841350                           SHARED_MEM_NAME,
    10851351                           SHARED_MEM_SIZE,
     
    11511417{
    11521418    int     rc;
    1153     ULONG   ulDummy;
    1154     rc = DosGetNamedSharedMem((PPVOID)&pShrMem,
     1419
     1420    rc = DosGetNamedSharedMem((PPVOID)(PVOID)&pShrMem,
    11551421                              SHARED_MEM_NAME,
    11561422                              PAG_READ | PAG_WRITE);
Note: See TracChangeset for help on using the changeset viewer.