Changeset 2020


Ignore:
Timestamp:
Jun 12, 2005, 1:52:12 PM (20 years ago)
Author:
bird
Message:

o Handle .cmd, .bat, .btm and hash-bang script files if DosExecPgm()

fails. (I'm a little bit uncertain about argv[0], but it appears to work.)

Location:
trunk/src/emx
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/emx/ChangeLog.LIBC

    • Property cvs2svn:cvs-rev changed from 1.52 to 1.53
    r2019 r2020  
    332005-06-11: knut st. osmundsen <bird-gccos2-spam@anduin.net>
    44    - libc:
    5         o The smallcnv stuff is gone, waste of space since we're not really into 
     5        o The smallcnv stuff is gone, waste of space since we're not really into
    66          static linking. Should've done this when switching to gdtoa.
    77        o Ported the msun and some other math bits from current FreeBSD libc.
     
    1010          if we're gonna catch up on the C99 bits and make libstdc++ happy.
    1111          There are some new headers, complex.h and fenv.h being the importan ones.
    12           float.h have gotten some updates while math.h is totally replaced. 
     12          float.h have gotten some updates while math.h is totally replaced.
    1313          More than 100 standard functions were added!
    14           NOTE: msun is using MATH_ERREXCEPT (math_errhandling) and not 
     14          NOTE: msun is using MATH_ERREXCEPT (math_errhandling) and not
    1515                MATH_ERRNO for error reporting.
    1616          I really hope this is not gonna uncover more OS/2 387 mess.
     17        o Handle .cmd, .bat, .btm and hash-bang script files if DosExecPgm()
     18          fails. (I'm a little bit uncertain about argv[0], but it appears to work.)
    1719
    18202005-06-05: knut st. osmundsen <bird-gccos2-spam@anduin.net>
  • trunk/src/emx/src/lib/sys/__spawnve.c

    • Property cvs2svn:cvs-rev changed from 1.15 to 1.16
    r2019 r2020  
    1111#define INCL_DOSPROCESS
    1212#define INCL_FSMACROS
     13#define INCL_DOSERRORS
    1314#include <os2emx.h>
    1415#include "b_fs.h"
     
    114115
    115116#define ADD(n) do { \
    116   while (arg_size + n > arg_alloc) \
     117  while (cbArgs + n > cbArgsBuf) \
    117118    { \
    118       arg_alloc += 512; \
    119       arg_buf = _trealloc (arg_buf, arg_alloc); \
    120       if (arg_buf == NULL) \
     119      cbArgsBuf += 512; \
     120      pszArgsBuf = _trealloc (pszArgsBuf, cbArgsBuf); \
     121      if (pszArgsBuf == NULL) \
    121122        { \
    122123          errno = ENOMEM; \
    123124          LIBCLOG_RETURN_INT(-1); \
    124125        } \
    125       arg_ptr = arg_buf + arg_size; \
     126      pszArg = pszArgsBuf + cbArgs; \
    126127    } \
    127   arg_size += n; } while (0)
    128 
    129 
    130 int __spawnve (struct _new_proc *np)
     128  cbArgs += n; } while (0)
     129
     130
     131int __spawnve(struct _new_proc *np)
    131132{
    132133    LIBCLOG_ENTER("np=%p:{mode=%#x}\n", (void *)np, np->mode);
    133     __LIBC_PSPMPROCESS    pEmbryo;
    134     ULONG                 mode;
    135     char *arg_ptr, *arg_buf;
    136     char *pgm_name, *base;
    137     const char *src, *s;
    138     size_t arg_size, arg_alloc, len;
    139     int i, quote, bs, method;
    140134    FS_VAR();
    141 
    142     arg_buf = NULL; arg_alloc = 0; arg_size = 0; arg_ptr = NULL;
    143135
    144136    /*
    145137     * Validate mode.
    146138     */
    147     mode = np->mode;
    148     switch (mode & 0xff)
     139    ULONG ulMode = np->mode;
     140    switch (ulMode & 0xff)
    149141    {
    150142        case P_WAIT:
     
    154146        default:
    155147            errno = EINVAL;
    156             LIBC_ASSERTM_FAILED("invalid mode 0x%08lx\n", mode);
     148            LIBC_ASSERTM_FAILED("invalid mode 0x%08lx\n", ulMode);
    157149            LIBCLOG_RETURN_INT(-1);
    158150    }
    159151
    160152    /*
    161      * Allocate space for the program name and check if it's an OS/2 shell.
     153     * Allocate space for the program name and resolve the filename.
    162154     */
    163     pgm_name = alloca (strlen ((const char *)np->fname_off) + 5);
    164     strcpy (pgm_name, (const char *)np->fname_off);
    165     _defext (pgm_name, "exe");
    166     base = _getname (pgm_name);
    167     method = 0;
    168     if (stricmp (base, "cmd.exe") == 0 || stricmp (base, "4os2.exe") == 0)
    169         method = 1;
     155    size_t cch = strlen((const char *)np->fname_off);
     156    char *pszPgmName = alloca(cch + 5);
     157    memcpy(pszPgmName, (const char *)np->fname_off, cch + 1);
     158    _defext(pszPgmName, "exe");
    170159    char szNativePath[PATH_MAX];
    171     int rc = __libc_back_fsResolve(pgm_name, BACKFS_FLAGS_RESOLVE_FULL, &szNativePath[0], NULL);
     160    int rc = __libc_back_fsResolve(pszPgmName, BACKFS_FLAGS_RESOLVE_FULL, &szNativePath[0], NULL);
    172161    if (rc)
    173162    {
    174         LIBC_ASSERTM_FAILED("Failed to resolve program name: '%s' rc=%d.\n", pgm_name, rc);
    175         errno = -rc;
    176         LIBCLOG_RETURN_INT(-1);
     163        if (pszPgmName[cch])
     164        {
     165            pszPgmName[cch] = '\0';
     166            rc = __libc_back_fsResolve(pszPgmName, BACKFS_FLAGS_RESOLVE_FULL, &szNativePath[0], NULL);
     167        }
     168        if (rc)
     169        {
     170            LIBC_ASSERTM_FAILED("Failed to resolve program name: '%s' rc=%d.\n", pszPgmName, rc);
     171            errno = -rc;
     172            LIBCLOG_RETURN_INT(-1);
     173        }
    177174    }
    178     pgm_name = &szNativePath[0];
     175    pszPgmName = &szNativePath[0];
    179176
    180177    /*
    181      * Process arguments.
     178     * cmd.exe and 4os2.exe needs different argument handling.
     179     * (1 == cmd or 4os2 shell, 0 == anything else)
    182180     */
    183     src = (const char *)np->arg_off;
     181    char *psz = _getname(pszPgmName);
     182    int method = stricmp(psz, "cmd.exe") == 0
     183              || stricmp(psz, "4os2.exe") == 0;
     184
     185    /*
     186     * Construct the commandline.
     187     */
     188    const char *pszSrc = (const char *)np->arg_off;
     189    char       *pszArgsBuf = NULL;
     190    size_t      cbArgsBuf = 0;
     191    char       *pszArg = NULL;
     192    size_t      cbArgs = 0;
    184193    if (np->arg_count > 0)
    185194    {
    186         ++src;                    /* skip flags byte */
    187         len = strlen (src) + 1;
    188         ADD (len);
    189         memcpy (arg_ptr, src, len);
    190         arg_ptr += len; src += len;
     195        ++pszSrc;                    /* skip flags byte */
     196        cch = strlen(pszSrc) + 1;
     197        ADD(cch);
     198        memcpy(pszArg, pszSrc, cch);
     199        pszArg += cch; pszSrc += cch;
    191200    }
     201    int i;
    192202    for (i = 1; i < np->arg_count; ++i)
    193203    {
    194204        if (i > 1)
    195205        {
    196             ADD (1);
    197             *arg_ptr++ = ' ';
    198         }
    199         ++src;                    /* skip flags byte */
    200         quote = FALSE;
    201         if (*src == 0)
    202             quote = TRUE;
    203         else if (mode & P_QUOTE)
    204         {
    205             if (src[0] == '@' && src[1] != 0)
    206                 quote = TRUE;
     206            ADD(1);
     207            *pszArg++ = ' ';
     208        }
     209        ++pszSrc;                    /* skip flags byte */
     210        BOOL fQuote = FALSE;
     211        if (*pszSrc == 0)
     212            fQuote = TRUE;
     213        else if (ulMode & P_QUOTE)
     214        {
     215            if (pszSrc[0] == '@' && pszSrc[1] != 0)
     216                fQuote = TRUE;
    207217            else
    208                 for (s = src; *s != 0; ++s)
    209                     if (*s == '?' || *s == '*')
    210                     {
    211                         quote = TRUE;
     218                for (psz = (char *)pszSrc; *psz != 0; ++psz)
     219                    if (*psz == '?' || *psz == '*')
     220                    {
     221                        fQuote = TRUE;
    212222                        break;
    213223                    }
    214224        }
    215         if (!quote)
    216             for (s = src; *s != 0; ++s)
    217                 if (*s == ' ' || *s == '\t' || (*s == '"' && method == 1))
    218                 {
    219                     quote = TRUE;
     225        if (!fQuote)
     226        {
     227            for (psz = (char *)pszSrc; *psz != 0; ++psz)
     228                if (*psz == ' ' || *psz == '\t' || (*psz == '"' && method == 1))
     229                {
     230                    fQuote = TRUE;
    220231                    break;
    221232                }
    222         if (quote)
    223         {
    224             ADD (1);
    225             *arg_ptr++ = '"';
    226         }
    227         bs = 0;
    228         while (*src != 0)
    229         {
    230             if (*src == '"' && method == 0)
     233        }
     234        if (fQuote)
     235        {
     236            ADD(1);
     237            *pszArg++ = '"';
     238        }
     239        size_t bs = 0;
     240        while (*pszSrc != 0)
     241        {
     242            if (*pszSrc == '"' && method == 0)
    231243            {
    232244                ++bs;
    233                 ADD (bs);
    234                 memset (arg_ptr, '\\', bs); arg_ptr += bs;
     245                ADD(bs);
     246                memset(pszArg, '\\', bs); pszArg += bs;
    235247                bs = 0;
    236248            }
    237             else if (*src == '\\' && method == 0)
     249            else if (*pszSrc == '\\' && method == 0)
    238250                ++bs;
    239251            else
    240252                bs = 0;
    241             ADD (1);
    242             *arg_ptr++ = *src;
    243             ++src;
    244         }
    245         if (quote)
    246         {
    247             ADD (1+bs);
    248             memset (arg_ptr, '\\', bs); arg_ptr += bs;
    249             *arg_ptr++ = '"';
    250         }
    251         ++src;
     253            ADD(1);
     254            *pszArg++ = *pszSrc;
     255            ++pszSrc;
     256        }
     257        if (fQuote)
     258        {
     259            ADD(1+bs);
     260            memset(pszArg, '\\', bs); pszArg += bs;
     261            *pszArg++ = '"';
     262        }
     263        ++pszSrc;
    252264    }
    253265    /* The arguments are an array of zero terminated strings, ending with an empty string. */
    254     ADD (2);
    255     *arg_ptr++ = '\0';
    256     *arg_ptr++ = '\0';
     266    ADD(2);
     267    *pszArg++ = '\0';
     268    *pszArg++ = '\0';
    257269
    258270
     
    261273     */
    262274    _fmutex_request(&__libc_gmtxExec, 0);
    263     pEmbryo = __libc_spmCreateEmbryo(getpid());
     275    __LIBC_PSPMPROCESS pEmbryo = __libc_spmCreateEmbryo(getpid());
    264276    if (pEmbryo)
    265277    {
     
    272284            RESULTCODES resc;
    273285            char        szObj[40];
    274             int         rc;
    275286
    276287            /*
     
    278289             */
    279290            FS_SAVE_LOAD();
    280             LIBCLOG_MSG("Calling DosExecPgm pgm: %s args: %s\\0%s\\0\\0\n", pgm_name, arg_buf, arg_buf + strlen(arg_buf) + 1);
    281             rc = DosExecPgm(szObj, sizeof(szObj), EXEC_ASYNCRESULT, (PCSZ)arg_buf, (PCSZ)np->env_off, &resc, (PCSZ)pgm_name);
     291            LIBCLOG_MSG("Calling DosExecPgm pgm: %s args: %s\\0%s\\0\\0\n", pszPgmName, pszArgsBuf, pszArgsBuf + strlen(pszArgsBuf) + 1);
     292            rc = DosExecPgm(szObj, sizeof(szObj), EXEC_ASYNCRESULT, (PCSZ)pszArgsBuf, (PCSZ)np->env_off, &resc, (PCSZ)pszPgmName);
     293            int cTries = 3;
     294            while (     (   rc == ERROR_INVALID_EXE_SIGNATURE
     295                         || rc == ERROR_BAD_EXE_FORMAT)
     296                   &&   --cTries > 0)
     297            {
     298                /*
     299                 * This could be a batch, rexx or hash bang script.
     300                 * The first two is recognized by the filename extension, the latter
     301                 * requires inspection of the first line of the file.
     302                 */
     303                char szLineBuf[256];
     304                const char *pszInterpreter = NULL;
     305                const char *pszInterpreterArgs = NULL;
     306                psz = _getext(pszPgmName);
     307                if (psz && (!stricmp(psz, ".cmd") || !stricmp(psz, ".bat") || !stricmp(psz, ".btm")))
     308                {
     309                    pszInterpreterArgs = "/C";
     310                    pszInterpreter = getenv("COMSPEC");
     311                    if (!pszInterpreter)
     312                    {
     313                        pszInterpreter = getenv("OS2_SHELL");
     314                        if (!pszInterpreter)
     315                            pszInterpreter = stricmp(psz, ".btm") ? "cmd.exe" : "4os2.exe";
     316                    }
     317
     318                    /* make sure the slashes in the script name goes the DOS way. */
     319                    psz = szNativePath;
     320                    while ((psz = strchr(szNativePath, '/')) != NULL)
     321                        *psz++ = '\\';
     322                }
     323                else
     324                {
     325                    /*
     326                     * Read the first line of the file into szLineBuf and terminate
     327                     * it stripping trailing blanks.
     328                     */
     329                    HFILE hFile = NULLHANDLE;
     330                    ULONG ulAction = 0;
     331                    int rc2 = DosOpen((PCSZ)pszPgmName, &hFile, &ulAction, 0, FILE_NORMAL,
     332                                      OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS,
     333                                      OPEN_FLAGS_SEQUENTIAL | OPEN_FLAGS_NOINHERIT | OPEN_SHARE_DENYNONE | OPEN_ACCESS_READONLY,
     334                                      NULL);
     335                    if (!rc2)
     336                    {
     337                        ULONG cbRead = 0;
     338                        rc2 = DosRead(hFile, szLineBuf, sizeof(szLineBuf) - 1, &cbRead);
     339                        DosClose(hFile);
     340                        if (!rc2)
     341                        {
     342                            szLineBuf[cbRead < sizeof(szLineBuf) ? cbRead : sizeof(szLineBuf) - 1] = '\0';
     343                            psz = strpbrk(szLineBuf, "\r\n");
     344                            if (psz)
     345                            {
     346                                register char ch;
     347                                while ((ch = *--psz) == ' ' || ch == '\t')
     348                                    /* nothing */;
     349                                psz[1] = '\0';
     350
     351                                /*
     352                                 * Check for '#[ \t]*!'
     353                                 */
     354                                psz = &szLineBuf[0];
     355                                if (*psz++ == '#')
     356                                {
     357                                    while ((ch = *psz) == ' ' && ch == '\t')
     358                                        psz++;
     359                                    if (*psz++ == '!')
     360                                    {
     361                                        while ((ch = *psz) == ' ' && ch == '\t')
     362                                            psz++;
     363                                        pszInterpreter = psz;
     364
     365                                        /*
     366                                         * Find end of interpreter and start of potential arguments.
     367                                         * I've never seen quoted interpreter names, so we won't bother with that yet.
     368                                         */
     369                                        while ((ch = *psz) != ' ' && ch != '\t' && ch != '\0')
     370                                            psz++;
     371                                        if (ch)
     372                                        {
     373                                            *psz++ = '\0';
     374                                            while ((ch = *psz) == ' ' && ch == '\t')
     375                                                psz++;
     376                                            if (ch)
     377                                                pszInterpreterArgs = psz;
     378                                        }
     379                                    } /* if bang */
     380                                } /* if hash */
     381                            } /* if full line */
     382                        } /* if read */
     383                    } /* if open */
     384                }
     385                if (!pszInterpreter)
     386                    break;
     387
     388                /*
     389                 * Squeeze the interpreter arguments + the program name into
     390                 * the argument buffer after argv[0].
     391                 * ASSUME that the arguments and program name require no escaping.
     392                 */
     393                size_t cchPgmName = strlen(pszPgmName);
     394                int cchInterpreterArgs = pszInterpreterArgs ? strlen(pszInterpreterArgs) : -1;
     395                BOOL fQuote = strpbrk(pszPgmName, " \t") != NULL;
     396                cch = cchPgmName + cchInterpreterArgs + 2 + 2 * fQuote;
     397
     398                /* grow and shift the argument buffer. */
     399                ADD(cch);
     400                psz = pszArgsBuf + strlen(pszArgsBuf) + 1;
     401                memmove(psz + cch, psz, cbArgs);
     402
     403                /* add arguments */
     404                if (pszInterpreterArgs)
     405                {
     406                    memcpy(psz, pszInterpreterArgs, cchInterpreterArgs);
     407                    psz += cchInterpreterArgs;
     408                    *psz++ = ' ';
     409                }
     410
     411                /* script name */
     412                if (fQuote)
     413                    *psz++ = '"';
     414                memcpy(psz, pszPgmName, cchPgmName);
     415                psz += cchPgmName;
     416                if (fQuote)
     417                    *psz++ = '"';
     418                *psz++ = ' ';
     419
     420                /*
     421                 * Resolve the interpreter name.
     422                 * If the specified name fails, we'll try search the path for it and
     423                 * also adding an .exe extension before we give up.
     424                 */
     425                rc = __libc_back_fsResolve(pszInterpreter, BACKFS_FLAGS_RESOLVE_FULL, &szNativePath[0], NULL);
     426                if (rc)
     427                {
     428                    char szPath[512];
     429                    _searchenv(pszInterpreter, "PATH", szPath); /** @todo _searchenv is not safe, it can easily overflow szPath! */
     430                    if (!szPath[0])
     431                    {
     432                        cch = strlen(pszInterpreter);
     433                        memcpy(szNativePath, pszInterpreter, cch + 1);
     434                        _defext(szNativePath, "exe");
     435                        if (szNativePath[cch])
     436                            _searchenv(szNativePath, "PATH", szPath);
     437                    }
     438                    if (szPath[0])
     439                        rc = __libc_back_fsResolve(szPath, BACKFS_FLAGS_RESOLVE_FULL, &szNativePath[0], NULL);
     440                    if (rc)
     441                        break;
     442                }
     443
     444                /*
     445                 * Try execute it.
     446                 */
     447                LIBCLOG_MSG("Calling DosExecPgm pgm: %s args: %s\\0%s\\0\\0\n", pszPgmName, pszArgsBuf, pszArgsBuf + strlen(pszArgsBuf) + 1);
     448                rc = DosExecPgm(szObj, sizeof(szObj), EXEC_ASYNCRESULT, (PCSZ)pszArgsBuf, (PCSZ)np->env_off, &resc, (PCSZ)pszPgmName);
     449            } /* while */
    282450            FS_RESTORE();
    283451            if (!rc)
     
    290458                __libc_spmRelease(pEmbryo);
    291459                doInheritDone();
    292                 if (arg_buf != NULL)
    293                     _tfree (arg_buf);
     460                if (pszArgsBuf != NULL)
     461                    _tfree(pszArgsBuf);
    294462                _fmutex_release(&__libc_gmtxExec);
    295463
     
    297465                 * Exit depends on the mode.
    298466                 */
    299                 switch (mode & 0xff)
     467                switch (ulMode & 0xff)
    300468                {
    301469                    /*
     
    332500                            LIBC_ASSERTM(pidEnded == pid, "Expected pid 0x%04lx and got 0x%04lx!\n", pid, pidEnded);
    333501
    334                             if (mode == P_OVERLAY)
     502                            if (ulMode == P_OVERLAY)
    335503                            {
    336504                                LIBCLOG_MSG("Calling DosExit(,0)\n");
     
    354522                /* won't ever get here! */
    355523            }
     524            else if (rc > 0)
     525                _sys_set_errno(rc);
    356526            else
    357                 _sys_set_errno (rc);
     527                errno = -rc;
    358528            doInheritDone();
    359529        }
     
    362532    }
    363533
    364     if (arg_buf != NULL)
    365         _tfree (arg_buf);
     534    if (pszArgsBuf != NULL)
     535        _tfree(pszArgsBuf);
    366536    _fmutex_release(&__libc_gmtxExec);
    367537    LIBCLOG_RETURN_INT(-1);
Note: See TracChangeset for help on using the changeset viewer.