VirtualBox

Changeset 3475 in kBuild for trunk


Ignore:
Timestamp:
Sep 16, 2020 9:18:31 PM (5 years ago)
Author:
bird
Message:

kash: exec.c/h+eval.c: Fixed no-rehashing-needed optimizations so they work for windows and OS/2 as well (UNIX-specific abspath detection). Cache the suffix found by stat_pc_exec_exts so that we don't have to repeat it 2 microseconds after find_command called it. Use the specialized shfile_stat variants where possible. eval.c: Fixed double free of commandname in evalcommand_doit.

Location:
trunk/src/kash
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/kash/eval.c

    r3458 r3475  
    10121012                                        exitshell(psh, psh->exitstatus);
    10131013                        }
    1014                         if (savecmdnamemalloc)
     1014                        else if (savecmdnamemalloc)
    10151015                                sh_free(psh, savecmdname);
    10161016                        if (e != -1) {
     
    10411041                                setvareq(psh, sp->text, VEXPORT|VSTACK);
    10421042                        envp = environment(psh);
    1043                         shellexec(psh, args->argv, envp, args->path, args->cmdentry.u.index);
     1043                        shellexec(psh, args->argv, envp, args->path,
     1044                                  args->cmdentry.u.n.index, args->cmdentry.u.n.suffix);
    10441045                        break;
    10451046                }
     
    14211422                for (sp = psh->cmdenviron; sp; sp = sp->next)
    14221423                        setvareq(psh, sp->text, VEXPORT|VSTACK);
    1423                 shellexec(psh, argv + 1, environment(psh), pathval(psh), 0);
     1424                shellexec(psh, argv + 1, environment(psh), pathval(psh), 0, -1);
    14241425        }
    14251426        return 0;
  • trunk/src/kash/exec.c

    r3438 r3475  
    4646#include <stdlib.h>
    4747#include <stddef.h>
     48#include <assert.h>
    4849
    4950/*
     
    9899//STATIC int builtinloc = -1;           /* index in path of %builtin, or -1 */
    99100//int exerrno = 0;                      /* Last exec error */
     101#ifdef PC_EXE_EXTS
     102STATIC const char * const g_exe_suffixes[] = { "", ".exe", ".cmd", ".btm", ".com" };
     103#endif
    100104
    101105
     
    107111STATIC void delete_cmd_entry(shinstance *);
    108112#ifdef PC_EXE_EXTS
    109 STATIC int stat_pc_exec_exts(shinstance *, char *fullname, struct stat *st, int has_ext);
     113STATIC int stat_pc_exec_exts(shinstance *, char *fullname, int has_ext, int *suffixp);
    110114#endif
    111115
     
    136140                case CMDUNKNOWN:
    137141                case CMDNORMAL:
    138                     dst->param.index = csrc->param.index;
     142                    dst->param.n.index = csrc->param.n.index;
     143                    dst->param.n.suffix = csrc->param.n.suffix;
    139144                    break;
    140145                case CMDFUNCTION:
     
    162167
    163168/*
     169 * Check if 'path' is an absolute (starts with root) path or not.
     170 */
     171K_INLINE isabspath(const char *path)
     172{
     173#if K_OS == K_OS_WINDOWS || K_OS == K_OS_OS2
     174        if (path[0] == '/' || path[0] == '\\') {
     175                if (   (path[1] == '/' || path[1] == '\\')
     176                    && (path[2] != '/' && path[2] != '\\' && path[2]))
     177                        return 1;
     178        } else if (path[0] && path[1] == ':' && (path[2] == '\\' || path[2] == '/') && isalpha(path[0])) {
     179                return 1;
     180        }
     181        return 0;
     182#else
     183        return path[0] == '/';
     184#endif
     185}
     186
     187/*
     188 * Checks if the filename include a path or not.
     189 */
     190K_INLINE haspath(const char *name)
     191{
     192#if K_OS == K_OS_WINDOWS || K_OS == K_OS_OS2
     193    return strchr(name, '/') != NULL
     194        || strchr(name, '\\') != NULL
     195        || (name[0] && name[1] == ':');
     196#else
     197    return strchr(name, '/') != NULL;
     198#endif
     199}
     200
     201
     202/*
    164203 * Exec a program.  Never returns.  If you change this routine, you may
    165204 * have to change the find_command routine as well.
     
    167206
    168207SH_NORETURN_1 void
    169 shellexec(shinstance *psh, char **argv, char **envp, const char *path, int idx)
     208shellexec(shinstance *psh, char **argv, char **envp, const char *path, int idx, int suffix)
    170209{
    171210        char *cmdname;
     
    189228        const int has_ext = 1;
    190229#endif
    191         TRACE((psh, "shellexec: argv[0]=%s idx=%d\n", argv0, idx));
    192         if (strchr(argv0, '/') != NULL) {
    193                 cmdname = stalloc(psh, argv0len + 5);
    194                 strcpy(cmdname, argv0);
     230        TRACE((psh, "shellexec: argv[0]=%s idx=%d suffix=%d\n", argv0, idx, suffix));
     231        if (haspath(argv0)) {
     232#ifdef PC_EXE_EXTS
     233                if (!has_ext && suffix && (unsigned)suffix < K_ELEMENTS(g_exe_suffixes)) {
     234                        size_t sufflen = strlen(g_exe_suffixes[suffix]);
     235                        cmdname = stalloc(psh, argv0len + sufflen + 1);
     236                        memcpy(cmdname, argv0, argv0len);
     237                        memcpy(cmdname + argv0len, g_exe_suffixes[suffix], sufflen + 1);
     238                } else
     239#endif
     240                {
     241                        cmdname = stalloc(psh, argv0len + 5);
     242                        memcpy(cmdname, argv0, argv0len + 1);
     243                }
    195244                tryexec(psh, cmdname, argv, envp, has_ext);
    196245                TRACE((psh, "shellexec: cmdname=%s\n", cmdname));
     
    214263                while ((cmdname = padvance(psh, &path, argv0)) != NULL) {
    215264                        if (--idx < 0 && psh->pathopt == NULL) {
     265#ifdef PC_EXE_EXTS
     266                                if (!has_ext && idx == -1 && suffix && (unsigned)suffix < K_ELEMENTS(g_exe_suffixes))
     267                                        strcat(cmdname, g_exe_suffixes[suffix]);
     268#endif
    216269                                tryexec(psh, cmdname, argv, envp, has_ext);
    217270                                if (errno != ENOENT && errno != ENOTDIR)
     
    250303#ifdef PC_EXE_EXTS
    251304        /* exploit the effect of stat_pc_exec_exts which adds the
    252          * correct extentions to the file.
    253          */
    254         struct stat st;
    255         if (!has_ext)
    256             stat_pc_exec_exts(psh, cmd, &st, 0);
     305         * correct extentions to the file. */
     306        if (!has_ext) {
     307                int suffix;
     308                int isreg = stat_pc_exec_exts(psh, cmd, 0, &suffix);
     309                assert(isreg > 0);
     310        }
    257311#endif
    258312#if defined(__INNOTEK_LIBC__) && defined(EXEC_HASH_BANG_SCRIPT)
     
    396450            /* nothing*/;
    397451        TRACE((psh, "hash bang '%s'\n", new[0]));
    398         shellexec(psh, new, envp, pathval(psh), 0);
     452        shellexec(psh, new, envp, pathval(psh), 0, -1);
    399453        /* NOTREACHED */
    400454}
     
    466520
    467521#ifdef PC_EXE_EXTS
    468 STATIC int stat_pc_exec_exts(shinstance *psh, char *fullname, struct stat *st, int has_ext)
    469 {
     522STATIC int stat_pc_exec_exts(shinstance *psh, char *fullname, int has_ext, int *suffixp)
     523{
     524    int isreg;
     525
    470526    /* skip the SYSV crap */
    471     if (shfile_stat(&psh->fdtab, fullname, st) >= 0)
    472         return 0;
     527    if ((isreg = shfile_stat_isreg(&psh->fdtab, fullname)) >= 1) {
     528        *suffixp = 0;
     529        return isreg;
     530    }
    473531    if (!has_ext && errno == ENOENT)
    474532    {
     533        /* Ignore non-regular files here. */
    475534        char *psz = strchr(fullname, '\0');
    476         memcpy(psz, ".exe", 5);
    477         if (shfile_stat(&psh->fdtab, fullname, st) >= 0)
    478             return 0;
    479         if (errno != ENOENT && errno != ENOTDIR)
    480             return -1;
    481 
    482         memcpy(psz, ".cmd", 5);
    483         if (shfile_stat(&psh->fdtab, fullname, st) >= 0)
    484             return 0;
    485         if (errno != ENOENT && errno != ENOTDIR)
    486             return -1;
    487 
    488         memcpy(psz, ".bat", 5);
    489         if (shfile_stat(&psh->fdtab, fullname, st) >= 0)
    490             return 0;
    491         if (errno != ENOENT && errno != ENOTDIR)
    492             return -1;
    493 
    494         memcpy(psz, ".com", 5);
    495         if (shfile_stat(&psh->fdtab, fullname, st) >= 0)
    496             return 0;
    497         if (errno != ENOENT && errno != ENOTDIR)
    498             return -1;
    499 
    500         memcpy(psz, ".btm", 5);
    501         if (shfile_stat(&psh->fdtab, fullname, st) >= 0)
    502             return 0;
    503         *psz = '\0';
     535        int i;
     536        for (i = 1 /*first entry is empty*/; i < K_ELEMENTS(g_exe_suffixes); i++) {
     537            strcpy(psz, g_exe_suffixes[i]);
     538            if ((isreg = shfile_stat_isreg(&psh->fdtab, fullname)) >= 1) {
     539                *suffixp = i;
     540                return isreg;
     541            }
     542            if (isreg < 0 && errno != ENOENT && errno != ENOTDIR)
     543                break;
     544        }
    504545    }
    505     return -1;
     546    *suffixp = -1;
     547    return isreg;
    506548}
    507549#endif /* PC_EXE_EXTS */
     
    567609        switch (cmdp->cmdtype) {
    568610        case CMDNORMAL:
    569                 idx = cmdp->param.index;
     611                idx = cmdp->param.n.index;
    570612                path = pathval(psh);
    571613                do {
     
    574616                } while (--idx >= 0);
    575617                out1str(psh, name);
     618#ifdef PC_EXE_EXTS
     619                if ((unsigned)cmdp->param.n.suffix < K_ELEMENTS(g_exe_suffixes))
     620                        out1str(psh, g_exe_suffixes[cmdp->param.n.suffix]);
     621#endif
    576622                break;
    577623        case CMDSPLBLTIN:
     
    614660        int idx;
    615661        int prev;
     662        int norehashoncd = 1;
    616663        char *fullname;
    617         struct stat statb;
    618664        int e;
    619665        int (*bltin)(shinstance*,int,char **);
     
    635681
    636682        /* If name contains a slash, don't use PATH or hash table */
    637         if (strchr(name, '/') != NULL) {
     683        if (haspath(name)) {
    638684                if (act & DO_ABS) {
    639                         while (shfile_stat(&psh->fdtab, name, &statb) < 0) {
     685                        while (shfile_stat_exists(&psh->fdtab, name) < 0) {
    640686#ifdef SYSV
    641687                                if (errno == EINTR)
     
    645691                                        e = errno;
    646692                                entry->cmdtype = CMDUNKNOWN;
    647                                 entry->u.index = -1;
     693                                entry->u.n.index = -1;
     694                                entry->u.n.suffix = -1;
    648695                                return;
    649696                        }
    650697                        entry->cmdtype = CMDNORMAL;
    651                         entry->u.index = -1;
     698                        entry->u.n.index = -1;
     699                        entry->u.n.suffix = -1;
    652700                        return;
    653701                }
    654702                entry->cmdtype = CMDNORMAL;
    655                 entry->u.index = 0;
     703                entry->u.n.index = 0;
     704                entry->u.n.suffix = 0;
    656705                return;
    657706        }
     
    703752                        prev = psh->builtinloc;
    704753                else
    705                         prev = cmdp->param.index;
     754                        prev = cmdp->param.n.index;
    706755        }
    707756
     
    723772loop:
    724773        while ((fullname = padvance(psh, &path, name)) != NULL) {
     774#ifdef PC_EXE_EXTS
     775                int suffix;
     776#endif
     777                int isreg;
    725778                stunalloc(psh, fullname);
    726779                idx++;
     
    738791                }
    739792                /* if rehash, don't redo absolute path names */
    740                 if (fullname[0] == '/' && idx <= prev) {
     793                if (idx <= prev && isabspath(fullname)) {
    741794                        if (idx < prev)
    742795                                goto loop;
     
    745798                }
    746799#ifdef PC_EXE_EXTS
    747                 while (stat_pc_exec_exts(psh, fullname, &statb, has_ext) < 0) {
     800                while ((isreg = stat_pc_exec_exts(psh, fullname, has_ext, &suffix)) < 0) {
    748801#else
    749                 while (shfile_stat(&psh->fdtab, fullname, &statb) < 0) {
     802                while ((isreg = shfile_stat_isreg(&psh->fdtab, fullname)) < 0) {
    750803#endif
    751804#ifdef SYSV
     
    759812                }
    760813                e = EACCES;     /* if we fail, this will be the error */
    761                 if (!S_ISREG(statb.st_mode))
     814                if (isreg < 1)
    762815                        goto loop;
    763816                if (psh->pathopt) {             /* this is a %func directory */
     
    794847                        cmdp = cmdlookup(psh, name, 1);
    795848                cmdp->cmdtype = CMDNORMAL;
    796                 cmdp->param.index = idx;
     849                cmdp->param.n.index = idx;
     850                cmdp->param.n.suffix = suffix;
    797851                INTON;
    798852                goto success;
     
    9711025                while ((cmdp = *pp) != NULL) {
    9721026                        if ((cmdp->cmdtype == CMDNORMAL &&
    973                              cmdp->param.index >= firstchange)
     1027                             cmdp->param.n.index >= firstchange)
    9741028                         || (cmdp->cmdtype == CMDBUILTIN &&
    9751029                             psh->builtinloc >= firstchange)) {
     
    10641118                cmdp->cmdtype = CMDUNKNOWN;
    10651119                cmdp->rehash = 0;
     1120                cmdp->param.n.index = 0;
     1121                cmdp->param.n.suffix = 0;
    10661122                strcpy(cmdp->cmdname, name);
    10671123                INTON;
     
    12291285                switch (entry.cmdtype) {
    12301286                case CMDNORMAL: {
    1231                         if (strchr(arg, '/') == NULL) {
     1287                        if (!haspath(arg)) {
    12321288                                const char *path = pathval(psh);
    12331289                                char *name;
    1234                                 int j = entry.u.index;
     1290                                int j = entry.u.n.index;
    12351291                                do {
    12361292                                        name = padvance(psh, &path, arg);
     
    12401296                                        out1fmt(psh, " is%s ",
    12411297                                            cmdp ? " a tracked alias for" : "");
    1242                                 out1fmt(psh, "%s\n", name);
     1298#ifdef PC_EXE_EXTS
     1299                                if ((unsigned)entry.u.n.suffix < K_ELEMENTS(g_exe_suffixes))
     1300                                        out1fmt(psh, "%s%s\n", name, g_exe_suffixes[entry.u.n.suffix]);
     1301                                else
     1302#endif
     1303                                        out1fmt(psh, "%s\n", name);
    12431304                        } else {
    12441305                                if (shfile_access(&psh->fdtab, arg, X_OK) == 0) {
  • trunk/src/kash/exec.h

    r3438 r3475  
    4747
    4848union param {
    49         int index;
     49        struct
     50        {
     51            int index;
     52            int suffix; /* PC suffix index */
     53        } n;
    5054        int (*bltin)(struct shinstance*, int, char**);
    5155        union node *func;
     
    7478void subshellinitexec(shinstance *, shinstance *);
    7579#endif
    76 SH_NORETURN_1 void shellexec(struct shinstance *, char **, char **, const char *, int) SH_NORETURN_2;
     80SH_NORETURN_1 void shellexec(struct shinstance *, char **, char **, const char *, int, int) SH_NORETURN_2;
    7781char *padvance(struct shinstance *, const char **, const char *);
    7882int hashcmd(struct shinstance *, int, char **);
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette