VirtualBox

Changeset 3438 in kBuild


Ignore:
Timestamp:
Sep 9, 2020 8:01:39 PM (4 years ago)
Author:
bird
Message:

kash: Hammering on threaded mode.

Location:
trunk/src/kash
Files:
30 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/kash/Makefile.kmk

    r3434 r3438  
    2626SUB_DEPTH = ../..
    2727include $(KBUILD_PATH)/subheader.kmk
     28
     29KASH_WIN_FORKED_MODE = 1
    2830
    2931#
     
    3537kash_ASTOOL = YASM
    3638kash_DEFS = lint SHELL SMALL
     39if "$(KBUILD_TARGET)" != "win" || defined(KASH_WIN_FORKED_MODE)
    3740kash_DEFS += SH_FORKED_MODE
     41endif
    3842kash_DEFS.debug = DEBUG=2
    3943kash_DEFS.haiku = BSD
     
    4448        BSD YY_NO_UNISTD_H \
    4549        SH_DEAL_WITH_CRLF PC_PATH_SEP PC_DRIVE_LETTERS PC_EXE_EXTS EXEC_HASH_BANG_SCRIPT \
    46 #       KASH_USE_FORKSHELL2
     50        KASH_USE_FORKSHELL2
    4751kash_DEFS.os2 = \
    4852        HAVE_SYS_SIGNAME HAVE_SYSCTL_H HAVE_SETPROGNAME PC_OS2_LIBPATHS \
     
    6771endif
    6872kash_CFLAGS.win.amd64 = -GS-
     73ifdef KASH_WIN_FORKED_MODE
    6974kash_LDFLAGS.win = -DYNAMICBASE:NO
     75endif
    7076kash_SOURCES = \
    7177        main.c \
     
    125131        $(kash_0_OUTDIR)/sys_signame.c \
    126132        strsignal.c \
    127         strlcpy.c \
     133        strlcpy.c
     134ifdef KASH_WIN_FORKED_MODE
     135kash_SOURCES.win += \
    128136        shfork-win.c \
    129137        shforkA-win.asm
     138endif
    130139
    131140kash_INTERMEDIATES = \
  • trunk/src/kash/alias.c

    r2290 r3438  
    6161STATIC struct alias **hashalias(shinstance *, char *);
    6262
     63#ifndef SH_FORKED_MODE
     64void
     65subshellinitalias(shinstance *psh, shinstance *inherit)
     66{
     67    unsigned i;
     68    unsigned left = inherit->aliases;
     69    if (left == 0)
     70        return;
     71    for (i = 0; i < K_ELEMENTS(inherit->atab); i++)
     72    {
     73        struct alias const *asrc = inherit->atab[i];
     74        if (asrc)
     75        {
     76            struct alias **ppdst = &psh->atab[i];
     77            do
     78            {
     79                if (*asrc->name)
     80                {
     81                    struct alias *dst = (struct alias *)ckmalloc(psh, sizeof(*dst));
     82                    dst->name = savestr(psh, asrc->name);
     83                    dst->val = savestr(psh, asrc->val);
     84                    dst->flag = asrc->flag;
     85                    *ppdst = dst;
     86                    ppdst = &dst->next;
     87                }
     88                left--;
     89                asrc = asrc->next;
     90            } while (asrc);
     91            *ppdst = NULL;
     92            if (left == 0)
     93                break;
     94        }
     95    }
     96}
     97#endif /* !SH_FORKED_MODE */
     98
    6399STATIC
    64100void
     
    111147        ap->next = *app;
    112148        *app = ap;
     149        psh->aliases++;
    113150        INTON;
    114151}
     
    138175                                ckfree(psh, ap->val);
    139176                                ckfree(psh, ap);
     177                                psh->aliases--;
    140178                                INTON;
    141179                        }
  • trunk/src/kash/alias.h

    r1233 r3438  
    4444};
    4545
     46#ifndef SH_FORKED_MODE
     47void subshellinitalias(shinstance *, shinstance *);
     48#endif
    4649struct alias *lookupalias(struct shinstance *, char *, int);
    4750char *get_alias_text(struct shinstance *, char *);
  • trunk/src/kash/bltin/kill.c

    r3409 r3438  
    6161killcmd(shinstance *psh, int argc, char *argv[])
    6262{
    63         int errors, numsig, pid;
     63        int errors, numsig;
    6464        char *ep;
    6565
     
    131131
    132132        for (errors = 0; argc; argc--, argv++) {
    133                 if (*argv[0] == '%') {
    134                         pid = getjobpgrp(psh, *argv);
     133                const char * const strpid = argv[0];
     134                shpid pid;
     135                if (*strpid == '%') {
     136                        pid = getjobpgrp(psh, strpid);
    135137                        if (pid == 0) {
    136                                 sh_warnx(psh, "illegal job id: %s", *argv);
     138                                sh_warnx(psh, "illegal job id: %s", strpid);
    137139                                errors = 1;
    138140                                continue;
    139141                        }
    140142                } else {
    141                         pid = strtol(*argv, &ep, 10);
    142                         if (!**argv || *ep) {
    143                                 sh_warnx(psh, "illegal process id: %s", *argv);
     143#if !defined(SH_FORKED_MODE) && defined(_MSC_VER)
     144                        pid = _strtoi64(strpid, &ep, 10);
     145#elif !defined(SH_FORKED_MODE)
     146                        pid = strtoll(strpid, &ep, 10);
     147#else
     148                        pid = strtol(strpid, &ep, 10);
     149#endif
     150                        if (!*strpid || *ep) {
     151                                sh_warnx(psh, "illegal process id: %s", strpid);
    144152                                errors = 1;
    145153                                continue;
     
    147155                }
    148156                if (sh_kill(psh, pid, numsig) == -1) {
    149                         sh_warn(psh, "%s", *argv);
     157                        sh_warn(psh, "%s", strpid);
    150158                        errors = 1;
    151159                }
  • trunk/src/kash/error.c

    r2651 r3438  
    165165                TRACEV((psh, msg, va2));
    166166                va_end(va2);
    167                 TRACE((psh, "\") pid=%d\n", sh_getpid(psh)));
     167                TRACE((psh, "\") pid=%" SHPID_PRI "\n", sh_getpid(psh)));
    168168        } else
    169                 TRACE((psh, "exverror(%d, NULL) pid=%d\n", cond, sh_getpid(psh)));
     169                TRACE((psh, "exverror(%d, NULL) pid=%" SHPID_PRI "\n", cond, sh_getpid(psh)));
    170170#endif
    171171        if (msg)
  • trunk/src/kash/eval.c

    r3437 r3438  
    225225        psh->displayhist = 1;   /* show history substitutions done with fc */
    226226#endif
    227         TRACE((psh, "pid %d, evaltree(%p: %d, %d) called\n",
     227        TRACE((psh, "pid %" SHPID_PRI ", evaltree(%p: %d, %d) called\n",
    228228               sh_getpid(psh), n, n->type, flags));
    229229        switch (n->type) {
     
    458458                args.backgnd = backgnd;
    459459                forkshell2(psh, jp, n, backgnd ? FORK_BG : FORK_FG,
    460                            evalsubshell_child, n, &args, sizeof(args), NULL);
     460                           evalsubshell_child, n, &args, sizeof(args), NULL);
    461461        }
    462462#else
     
    578578                        args.pip[1] = pip[1];
    579579                        forkshell2(psh, jp, lp->n, n->npipe.backgnd ? FORK_BG : FORK_FG,
    580                                    evalpipe_child, lp->n, &args, sizeof(args), NULL);
     580                                   evalpipe_child, lp->n, &args, sizeof(args), NULL);
    581581                }
    582582#else
     
    677677                        args.pip[1] = pip[1];
    678678                        forkshell2(psh, jp, n, FORK_NOJOB,
    679                                    evalbackcmd_child, n, &args, sizeof(args), NULL);
     679                                   evalbackcmd_child, n, &args, sizeof(args), NULL);
    680680                }
    681681#else
     
    894894                        volatile int temp_path = 0;
    895895                        char *volatile savecmdname;
     896                        int volatile savecmdnamemalloc;
    896897                        volatile int e;
    897898                        int mode;
     
    909910                        savehandler = psh->handler;
    910911                        savecmdname = psh->commandname;
     912                        savecmdnamemalloc = psh->commandnamemalloc;
    911913                        psh->handler = &jmploc;
    912914                        if (!setjmp(jmploc.loc)) {
     
    930932                                listsetvar(psh, args->varlist.list,
    931933                                        args->cmdentry.cmdtype == CMDSPLBLTIN ? 0 : VNOSET);
     934                                psh->commandnamemalloc = 0;
    932935                                psh->commandname = args->argv[0];
    933936                                /* initialize nextopt */
     
    962965                        if (e != EXSHELLPROC) {
    963966                                psh->commandname = savecmdname;
     967                                psh->commandnamemalloc = savecmdnamemalloc;
    964968                                if (args->flags & EV_EXIT)
    965969                                        exitshell(psh, psh->exitstatus);
    966970                        }
     971                        if (savecmdnamemalloc)
     972                                sh_free(psh, savecmdname);
    967973                        if (e != -1) {
    968974                                if ((e != EXERROR && e != EXEXEC)
  • trunk/src/kash/exec.c

    r3437 r3438  
    4545#include <stdio.h>
    4646#include <stdlib.h>
     47#include <stddef.h>
    4748
    4849/*
     
    112113extern char *const parsekwd[];
    113114
     115#ifndef SH_FORKED_MODE
     116void
     117subshellinitexec(shinstance *psh, shinstance *inherit)
     118{
     119    unsigned i;
     120    for (i = 0; i < K_ELEMENTS(inherit->cmdtable); i++) {
     121        struct tblentry const *csrc = inherit->cmdtable[i];
     122        if (!csrc) {
     123        } else {
     124            struct tblentry **ppdst = &psh->cmdtable[i];
     125            do
     126            {
     127                size_t const namesize = strlen(csrc->cmdname) + 1;
     128                size_t const entrysize = offsetof(struct tblentry, cmdname) + namesize;
     129                struct tblentry *dst = (struct tblentry *)ckmalloc(psh, entrysize);
     130                memcpy(dst->cmdname, csrc->cmdname, namesize);
     131                dst->rehash = csrc->rehash;
     132                dst->cmdtype = csrc->cmdtype;
     133
     134                dst->param.func = NULL;
     135                switch (csrc->cmdtype) {
     136                case CMDUNKNOWN:
     137                case CMDNORMAL:
     138                    dst->param.index = csrc->param.index;
     139                    break;
     140                case CMDFUNCTION:
     141                    dst->param.func = copyfunc(psh, csrc->param.func); /** @todo optimize function allocations */
     142                    break;
     143                case CMDBUILTIN:
     144                case CMDSPLBLTIN:
     145                    dst->param.bltin = csrc->param.bltin;
     146                    break;
     147                }
     148
     149                *ppdst = dst;
     150                ppdst = &dst->next;
     151
     152                csrc = csrc->next;
     153            } while (csrc);
     154            *ppdst = NULL;
     155        }
     156    }
     157
     158    psh->builtinloc = inherit->builtinloc;
     159}
     160#endif /* SH_FORKED_MODE */
     161
     162
    114163/*
    115164 * Exec a program.  Never returns.  If you change this routine, you may
     
    222271                initshellproc(psh);
    223272                setinputfile(psh, cmd, 0);
     273                if (psh->commandnamemalloc) {
     274                    sh_free(psh, psh->commandname);
     275                    psh->commandnamemalloc = 0;
     276                }
     277                if (psh->arg0malloc)
     278                    sh_free(psh, psh->arg0);
    224279                psh->commandname = psh->arg0 = savestr(psh, argv[0]);
     280                psh->arg0malloc = 1;
    225281#ifdef EXEC_HASH_BANG_SCRIPT
    226282                pgetc(psh); pungetc(psh);               /* fill up input buffer */
  • trunk/src/kash/exec.h

    r3435 r3438  
    7171#endif
    7272
     73#ifndef SH_FORKED_MODE
     74void subshellinitexec(shinstance *, shinstance *);
     75#endif
    7376SH_NORETURN_1 void shellexec(struct shinstance *, char **, char **, const char *, int) SH_NORETURN_2;
    7477char *padvance(struct shinstance *, const char **, const char *);
  • trunk/src/kash/expand.c

    r2653 r3438  
    8989
    9090STATIC void argstr(shinstance *, char *, int);
     91STATIC void expari(shinstance *, int);
    9192STATIC char *exptilde(shinstance *, char *, int);
    9293STATIC void expbackq(shinstance *, union node *, int, int);
     
    106107STATIC int pmatch(char *, char *, int);
    107108STATIC char *cvtnum(shinstance *, int, char *);
     109STATIC char *cvtnum64(shinstance *, KI64, char *);
    108110
    109111/*
     
    343345 * evaluate, place result in (backed up) result, adjust string position.
    344346 */
    345 void
     347STATIC void
    346348expari(shinstance *psh, int flag)
    347349{
     
    869871        switch (*name) {
    870872        case '$':
     873#ifndef SH_FORKED_MODE
     874                psh->expdest = cvtnum64(psh, psh->rootpid, psh->expdest);
     875                break;
     876#else
    871877                num = psh->rootpid;
    872878                goto numvar;
     879#endif
    873880        case '?':
    874881                num = psh->exitstatus;
     
    876883        case '#':
    877884                num = psh->shellparam.nparam;
    878                 goto numvar;
    879         case '!':
    880                 num = psh->backgndpid;
    881885numvar:
    882886                psh->expdest = cvtnum(psh, num, psh->expdest);
    883887                break;
     888        case '!':
     889#ifndef SH_FORKED_MODE
     890                psh->expdest = cvtnum64(psh, psh->backgndpid, psh->expdest);
     891                break;
     892#else
     893                num = psh->backgndpid;
     894                goto numvar;
     895#endif
    884896        case '-':
    885897                for (i = 0; psh->optlist[i].name; i++) {
     
    15611573}
    15621574
     1575STATIC char *
     1576cvtnum64(shinstance *psh, KI64 num, char *buf)
     1577{
     1578        char temp[32];
     1579        int neg = num < 0;
     1580        char *p = temp + 31;
     1581
     1582        temp[31] = '\0';
     1583
     1584        do {
     1585                *--p = num % 10 + '0';
     1586        } while ((num /= 10) != 0);
     1587
     1588        if (neg)
     1589                *--p = '-';
     1590
     1591        while (*p)
     1592                STPUTC(psh, *p++, buf);
     1593        return buf;
     1594}
     1595
    15631596/*
    15641597 * Do most of the work for wordexp(3).
  • trunk/src/kash/expand.h

    r1233 r3438  
    6565void expandhere(struct shinstance *, union node *, int);
    6666void expandarg(struct shinstance *, union node *, struct arglist *, int);
    67 void expari(struct shinstance *, int);
    6867int patmatch(struct shinstance *, char *, char *, int);
    6968void rmescapes(struct shinstance *, char *);
  • trunk/src/kash/jobs.c

    r3437 r3438  
    6464#include "error.h"
    6565#include "mystring.h"
     66#include "init.h"
    6667#include "shinstance.h"
    6768
     
    7980STATIC void freejob(shinstance *, struct job *);
    8081STATIC struct job *getjob(shinstance *, const char *, int);
    81 STATIC int dowait(shinstance *, int, struct job *);
    82 STATIC int waitproc(shinstance *, int, struct job *, int *);
     82STATIC shpid dowait(shinstance *, int, struct job *);
     83STATIC shpid waitproc(shinstance *, int, struct job *, int *);
    8384STATIC void cmdtxt(shinstance *, union node *);
    8485STATIC void cmdlist(shinstance *, union node *, int);
    8586STATIC void cmdputs(shinstance *, const char *);
     87STATIC shpid forkparent(shinstance *psh, struct job *jp, union node *n, int mode, shpid pid);
     88STATIC void forkchild(shinstance *psh, shpid pgrp, union node *n, int mode);
    8689#ifdef KASH_USE_FORKSHELL2
    87 static int forkparent(shinstance *psh, struct job *jp, union node *n, int mode, pid_t pid);
    88 static void forkchild(shinstance *psh, struct job *jp, union node *n, int mode);
     90# ifndef SH_FORKED_MODE
     91struct forkshell2args
     92{
     93        shinstance *psh;
     94        int mode;
     95        shpid pgrp;     /**< The forkchild() pgrp argument (-1 if not in group). */
     96        union node *n;
     97        void *argp;     /**< Points to child callback data following this structure. */
     98        int (* child)(shinstance *, union node *, void *);
     99        struct stackmark smark; /* do we need this? */
     100};
     101static int forkshell2_thread(shinstance *psh, void *argp);
     102# endif
    89103#endif
    90104
     
    328342        if (mode & SHOW_PGID) {
    329343                /* just output process (group) id of pipeline */
    330                 outfmt(out, "%ld\n", (long)jp->ps->pid);
     344                outfmt(out, "%" SHPID_PRI "\n", jp->ps->pid);
    331345                return;
    332346        }
     
    382396                col = strlen(s);
    383397                if (mode & SHOW_PID) {
    384                         fmtstr(s + col, 16, "%ld ", (long)ps->pid);
     398                        fmtstr(s + col, 16, "%" SHPID_PRI " ", ps->pid);
    385399                             col += strlen(s + col);
    386400                }
     
    475489        int jobno;
    476490        struct job *jp;
    477         int silent = 0, gotpid;
     491        int silent = 0;
     492        shpid gotpid;
    478493
    479494        TRACE((psh, "showjobs(%x) called\n", mode));
     
    607622        jp = getjob(psh, *psh->argptr, 0);
    608623        for (i = 0 ; i < jp->nprocs ; ) {
    609                 out1fmt(psh, "%ld", (long)jp->ps[i].pid);
     624                out1fmt(psh, "%" SHPID_PRI, jp->ps[i].pid);
    610625                out1c(psh, ++i < jp->nprocs ? ' ' : '\n');
    611626        }
     
    613628}
    614629
    615 int
     630shpid
    616631getjobpgrp(shinstance *psh, const char *name)
    617632{
     
    785800
    786801#ifndef KASH_USE_FORKSHELL2
    787 int
     802shpid
    788803forkshell(shinstance *psh, struct job *jp, union node *n, int mode)
    789804{
     
    798813                return -1; /* won't get here */
    799814        case 0:
    800                 forkchild(psh, jp, n, mode);
     815                forkchild(psh, jp == NULL || jp->nprocs == 0 ? -1 : jp->ps[0].pid, n, mode);
    801816                return 0;
    802817        default:
     
    805820}
    806821#else /* KASH_USE_FORKSHELL2 */
    807 int forkshell2(struct shinstance *psh, struct job *jp, union node *n, int mode,
     822shpid
     823forkshell2(shinstance *psh, struct job *jp, union node *n, int mode,
    808824               int (*child)(struct shinstance *, void *, union node *),
    809825               union node *nchild, void *argp, size_t arglen,
    810826               void (*setupchild)(struct shinstance *, struct shinstance *, void *))
    811827{
    812         pid_t pid;
    813 
    814         TRACE((psh, "forkshell2(%%%d, %p, %d, %p, %p, %p, %d) called\n", jp - psh->jobtab, n, mode, child, nchild, argp, (int)arglen));
     828        shpid pid;
     829
     830# ifdef SH_FORKED_MODE
     831        /*
     832         * fork variant.
     833         */
    815834        pid = sh_fork(psh);
    816835        if (pid == 0)
    817836        {
    818837                /* child */
    819                 forkchild(psh, jp, n, mode);
    820                 sh_exit(psh, child(psh, nchild, argp));
     838                forkchild(psh, jp == NULL || jp->nprocs == 0 ? -1 : jp->ps[0].pid, n, mode);
     839                sh__exit(psh, child(psh, nchild, argp));
    821840                return 0;
    822841        }
     
    831850        error(psh, "Cannot fork");
    832851        return -1; /* won't get here */
    833 }
    834 #endif
    835 
    836 #ifdef KASH_USE_FORKSHELL2
    837 static
    838 #endif
    839 int
    840 forkparent(shinstance *psh, struct job *jp, union node *n, int mode, pid_t pid)
    841 {
    842         int pgrp;
     852
     853# else
     854        /*
     855         * Clone the shell and start a thread to service the subshell.
     856         */
     857        struct shinstance *pshchild;
     858
     859        TRACE((psh, "forkshell2(%%%d, %p, %d, %p, %p, %p, %d) called\n",
     860                   jp - psh->jobtab, n, mode, child, nchild, argp, (int)arglen));
     861
     862        pshchild = sh_create_child_shell(psh);
     863        if (pshchild) {
     864                /* pack arguments */
     865                struct forkshell2args *args = (struct forkshell2args *)sh_calloc(pshchild, sizeof(*args) + arglen, 1);
     866                args->psh = pshchild;
     867                args->argp = memcpy(args + 1, argp, arglen);
     868                args->child = child;
     869                args->mode = mode;
     870                args->pgrp = jp == NULL || jp->nprocs == 0 ? -1 : jp->ps[0].pid;
     871                setstackmark(pshchild, &args->smark);
     872                args->n = copyparsetree(pshchild, n);
     873                if (setupchild)
     874                        setupchild(pshchild, psh, args->argp);
     875
     876                /* start the thread */
     877                pid = sh_thread_start(psh, pshchild, forkshell2_thread, args);
     878                if (pid >= 0)
     879                        return forkparent(psh, jp, n, mode, pid);
     880                error(psh, "sh_start_child_thread failed (%d)!", (int)pid);
     881        }
     882        else
     883                error(psh, "sh_create_child_shell failed!");
     884        return -1;
     885# endif
     886}
     887#endif
     888
     889static shpid
     890forkparent(shinstance *psh, struct job *jp, union node *n, int mode, shpid pid)
     891{
     892        shpid pgrp;
    843893
    844894        if (psh->rootshell && mode != FORK_NOJOB && mflag(psh)) {
     
    860910                        commandtext(psh, ps, n);
    861911        }
    862         TRACE((psh, "In parent shell:  child = %d\n", pid));
     912        TRACE((psh, "In parent shell:  child = %" SHPID_PRI "\n", pid));
    863913        return pid;
    864914}
    865915
    866 #ifdef KASH_USE_FORKSHELL2
    867 static
    868 #endif
    869 void
    870 forkchild(shinstance *psh, struct job *jp, union node *n, int mode)
     916static void
     917forkchild(shinstance *psh, shpid pgrp, union node *n, int mode)
    871918{
    872919        int wasroot;
    873         int pgrp;
    874920        const char *devnull = _PATH_DEVNULL;
    875921        const char *nullerr = "Can't open %s";
    876922
    877923        wasroot = psh->rootshell;
    878         TRACE((psh, "Child shell %d\n", sh_getpid(psh)));
     924        TRACE((psh, "Child shell %" SHPID_PRI "\n", sh_getpid(psh)));
    879925        psh->rootshell = 0;
    880926
     
    884930        psh->jobctl = 0;                /* do job control only in root shell */
    885931        if (wasroot && mode != FORK_NOJOB && mflag(psh)) {
    886                 if (jp == NULL || jp->nprocs == 0)
     932                if (pgrp == -1)
    887933                        pgrp = sh_getpid(psh);
    888                 else
    889                         pgrp = jp->ps[0].pid;
    890934                /* This can fail because we are doing it in the parent also.
    891935                   And we must ignore SIGTTOU at this point or we'll be stopped! */
     
    898942                setsignal(psh, SIGTSTP);
    899943                setsignal(psh, SIGTTOU);
    900         } else if (mode == FORK_BG) {
     944        } else
     945#endif
     946        if (mode == FORK_BG) {
    901947                ignoresig(psh, SIGINT);
    902948                ignoresig(psh, SIGQUIT);
    903                 if ((jp == NULL || jp->nprocs == 0) &&
    904                     ! fd0_redirected_p(psh)) {
     949                if (pgrp == -1 && ! fd0_redirected_p(psh)) {
    905950                        shfile_close(&psh->fdtab, 0);
    906951                        if (shfile_open(&psh->fdtab, devnull, O_RDONLY, 0) != 0)
     
    908953                }
    909954        }
    910 #else
    911         if (mode == FORK_BG) {
    912                 ignoresig(psh, SIGINT);
    913                 ignoresig(psh, SIGQUIT);
    914                 if ((jp == NULL || jp->nprocs == 0) &&
    915                     ! fd0_redirected_p(psh)) {
    916                         shfile_close(&psh->fdtab, 0);
    917                         if (shfile_open(&psh->fdtab, devnull, O_RDONLY, 0) != 0)
    918                                 error(psh, nullerr, devnull);
    919                 }
    920         }
    921 #endif
    922955        if (wasroot && iflag(psh)) {
    923956                setsignal(psh, SIGINT);
     
    928961        psh->jobs_invalid = 1;
    929962}
     963
     964#if defined(KASH_USE_FORKSHELL2) && !defined(SH_FORKED_MODE)
     965/** thread procedure */
     966static int forkshell2_thread(shinstance *psh, void *argp)
     967{
     968        struct forkshell2args * volatile volargs = (struct forkshell2args *)argp;
     969        struct jmploc jmp;
     970        TRACE2((psh, "forkshell2_thread:\n"));
     971
     972        if (setjmp(jmp.loc) == 0) {
     973                struct forkshell2args * const args = volargs;
     974
     975                forkchild(psh, args->pgrp, args->n, args->mode);
     976
     977                psh->handler = &jmp;
     978                return args->child(psh, args->n, args->argp);
     979        }
     980
     981        /*
     982         * (We longjmp'ed here.)
     983         *
     984         * This is copied from main() and simplified:
     985         */
     986        for (;;) {
     987                psh = volargs->psh; /* longjmp paranoia */
     988
     989                if (psh->exception != EXSHELLPROC) {
     990                        if (psh->exception == EXEXEC)
     991                                psh->exitstatus = psh->exerrno;
     992                        else if (psh->exception == EXERROR)
     993                                psh->exitstatus = 2;
     994                        TRACE2((psh, "forkshell2_thread: exception=%d -> exitshell2(,%d)\n", psh->exception, psh->exitstatus));
     995                        return exitshell2(psh, psh->exitstatus);
     996                }
     997
     998                /* EXSHELLPROC - tryexec gets us here and it wants to run a program
     999                   hoping (?) it's a shell script.  We must reset the shell state and
     1000                   turn ourselves into a root shell before doing so. */
     1001                TRACE2((psh, "forkshell2_thread: exception=EXSHELLPROC\n"));
     1002                psh->rootpid = /*getpid()*/ psh->pid;
     1003                psh->rootshell = 1;
     1004                psh->minusc = NULL;
     1005
     1006                reset(psh);
     1007                popstackmark(psh, &volargs->smark);
     1008
     1009                FORCEINTON;                             /* enable interrupts */
     1010
     1011                /* state3: */
     1012                if (sflag(psh) == 0) {
     1013# ifdef SIGTSTP
     1014                        static int sigs[] =  { SIGINT, SIGQUIT, SIGHUP, SIGPIPE, SIGTSTP };
     1015# else
     1016                        static int sigs[] =  { SIGINT, SIGQUIT, SIGHUP, SIGPIPE };
     1017# endif
     1018                        unsigned i;
     1019                        for (i = 0; i < K_ELEMENTS(sigs); i++)
     1020                                setsignal(psh, sigs[i]);
     1021                }
     1022
     1023                if (setjmp(jmp.loc) == 0) {
     1024                        psh->handler = &jmp;
     1025                        cmdloop(psh, 1);
     1026                        TRACE2((psh, "forkshell2_thread: cmdloop returned -> exitshell2(,%d)\n", psh->exitstatus));
     1027                        return exitshell2(psh, psh->exitstatus);
     1028                }
     1029        }
     1030}
     1031#endif
     1032
    9301033
    9311034/*
     
    9521055{
    9531056#if JOBS
    954         int mypgrp = sh_getpgrp(psh);
     1057        shpid mypgrp = sh_getpgrp(psh);
    9551058#endif
    9561059        int status;
     
    10091112 */
    10101113
    1011 STATIC int
     1114STATIC shpid
    10121115dowait(shinstance *psh, int block, struct job *job)
    10131116{
    1014         int pid;
     1117        shpid pid;
    10151118        int status;
    10161119        struct procstat *sp;
     
    10231126        do {
    10241127                pid = waitproc(psh, block, job, &status);
    1025                 TRACE((psh, "wait returns pid %d, status %d\n", pid, status));
     1128                TRACE((psh, "wait returns pid %" SHPID_PRI ", status %d\n", pid, status));
    10261129        } while (pid == -1 && errno == EINTR && psh->gotsig[SIGINT - 1] == 0);
    10271130        if (pid <= 0)
     
    10371140                                        continue;
    10381141                                if (sp->pid == pid) {
    1039                                         TRACE((psh, "Job %d: changing status of proc %d from 0x%x to 0x%x\n", jp - psh->jobtab + 1, pid, sp->status, status));
     1142                                        TRACE((psh, "Job %d: changing status of proc %" SHPID_PRI " from 0x%x to 0x%x\n",
     1143                                                   jp - psh->jobtab + 1, pid, sp->status, status));
    10401144                                        sp->status = status;
    10411145                                        thisjob = jp;
     
    10861190 * rather than blocking.
    10871191 */
    1088 STATIC int
     1192STATIC shpid
    10891193waitproc(shinstance *psh, int block, struct job *jp, int *status)
    10901194{
  • trunk/src/kash/jobs.h

    r3437 r3438  
    4242#define FORK_NOJOB 2
    4343
     44#define FORK_JUST_IO 4          /* forking I/O subprocess/thread (here doc). */
     45
    4446/* mode flags for showjob(s) */
    4547#define SHOW_PGID       0x01    /* only show pgid - for jobs -p */
     
    6163
    6264struct procstat {
    63         pid_t   pid;            /* process id */
     65        shpid   pid;            /* process id */
    6466        int     status;         /* last process status from wait() */
    6567        char    cmd[MAXCMDTEXT];/* text of command being run */
     
    7072        struct procstat *ps;    /* status or processes when more than one */
    7173        int     nprocs;         /* number of processes */
    72         pid_t   pgrp;           /* process group of this job */
     74        shpid   pgrp;           /* process group of this job */ /**< @todo is job:pgrp used anywhere? */
    7375        char    state;
    7476#define JOBRUNNING      0       /* at least one proc running */
     
    9698struct job *makejob(struct shinstance *, union node *, int);
    9799#ifdef KASH_USE_FORKSHELL2
    98 int forkshell2(struct shinstance *, struct job *, union node *, int,
    99                int (*child)(struct shinstance *, void *, union node *),
    100                union node *, void *, size_t,
    101                void (*setupchild)(struct shinstance *, struct shinstance *, void *));
     100shpid forkshell2(struct shinstance *, struct job *, union node *, int,
     101                 int (*child)(struct shinstance *, void *, union node *),
     102                 union node *, void *, size_t,
     103                 void (*setupchild)(struct shinstance *, struct shinstance *, void *));
    102104#else
    103 int forkshell(struct shinstance *, struct job *, union node *, int);
    104 void forkchild(struct shinstance *, struct job *, union node *, int);
    105 int forkparent(struct shinstance *, struct job *, union node *, int, pid_t);
     105shpid forkshell(struct shinstance *, struct job *, union node *, int);
    106106#endif
    107107int waitforjob(struct shinstance *, struct job *);
    108108int stoppedjobs(struct shinstance *);
    109109void commandtext(struct shinstance *, struct procstat *, union node *);
    110 int getjobpgrp(struct shinstance *, const char *);
     110shpid getjobpgrp(struct shinstance *, const char *);
    111111
    112112#if ! JOBS
  • trunk/src/kash/main.c

    r3435 r3438  
    4545#endif
    4646
     47#include <assert.h>
    4748#include <errno.h>
    4849#include <stdio.h>
     
    101102
    102103int
    103 #if K_OS == K_OS_WINDOWS
     104#if K_OS == K_OS_WINDOWS && defined(SH_FORKED_MODE)
    104105real_main(int argc, char **argv, char **envp)
    105106#else
     
    130131         * Create the root shell instance.
    131132         */
    132         psh = sh_create_root_shell(NULL, argc, argv, envp);
     133        psh = sh_create_root_shell(argv, envp);
    133134        if (!psh)
    134135                return 2;
    135136        shthread_set_shell(psh);
    136         shell_main(psh, argc, psh->argptr);
     137        shell_main(psh, argc, psh->orgargv);
    137138        /* Not reached. */
    138139        return 89;
     
    406407
    407408        if (argc >= 2) {                /* That's what SVR2 does */
     409                char * const savedcommandname = psh->commandname;
     410                int const savedcommandnamemalloc = psh->commandnamemalloc;
    408411                char *fullname;
    409412                struct stackmark smark;
     
    413416                setinputfile(psh, fullname, 1);
    414417                psh->commandname = fullname;
     418                psh->commandnamemalloc = 0;
    415419                cmdloop(psh, 0);
    416420                popfile(psh);
     421                psh->commandname = savedcommandname;
     422                psh->commandnamemalloc = savedcommandnamemalloc;
    417423                popstackmark(psh, &smark);
    418424        }
  • trunk/src/kash/options.c

    r2652 r3438  
    4141#endif
    4242
     43#include <assert.h>
    4344#include <stdlib.h>
    4445
     
    7778STATIC int getopts(shinstance *, char *, char *, char **, char ***, char **);
    7879
     80#ifndef SH_FORKED_MODE
     81void
     82subshellinitoptions(shinstance *psh, shinstance *inherit)
     83{
     84    unsigned i;
     85    int left;
     86    const char *arg;
     87    memcpy(&psh->optlist[0], &inherit->optlist[0], sizeof(psh->optlist));
     88
     89    /** @todo opimize: skip this when executing builtins. */
     90    /* Whether the subshell uses argptr/shellparam/arg0 or replaces them depends
     91       on whether the shell will execute a builtin command or not.
     92
     93       orgargv is already set by the shinstance.c core code, scan the original
     94       again and update arg0, shellparm, argptr and optptr. */
     95
     96    /* arg0 is either something from orgargv, or in the EXSHELLPROC case a
     97       separate allocation that we need to dupe here. The (new) arg0malloc
     98       flag indicates which. */
     99    i = 0;
     100    psh->arg0malloc = inherit->arg0malloc;
     101    if (inherit->arg0malloc) {
     102        psh->arg0 = savestr(psh, inherit->arg0);
     103    } else {
     104        while ((arg = inherit->orgargv[i]) != NULL) {
     105            if (inherit->arg0 == arg) {
     106                psh->arg0 = psh->orgargv[i];
     107                break;
     108            }
     109            i++;
     110        }
     111        assert(psh->arg0 != NULL);
     112    }
     113
     114    /* eval.h's commandname is same as arg0 when set unless we're doing a dot-include. */
     115    if (inherit->commandname) {
     116        if (inherit->commandname == inherit->arg0) {
     117            psh->commandname = psh->arg0;
     118        } else {
     119            psh->commandname = savestr(psh, inherit->commandname);
     120            psh->commandnamemalloc = 1;
     121        }
     122    }
     123
     124    /* shellparam is either pointing right after arg0 in orgargv, though it may
     125       also be a separately allocated thing (see setparam), or pointing to the
     126       arguments of a shell function we're executing (see eval.c).  All in all,
     127       it's simpler if we just copy the whole darn thing, ASSUMING no
     128       modifications will be made that are needed to be visible elsewhere.
     129       */
     130    psh->shellparam.malloc = 1;
     131    psh->shellparam.reset  = inherit->shellparam.reset;
     132    psh->shellparam.nparam = left = inherit->shellparam.nparam;
     133    assert(left >= 0);
     134    psh->shellparam.p = (char **)ckmalloc(psh, left + 1);
     135    psh->shellparam.p[left] = NULL;
     136    while (left-- > 0) {
     137        arg = inherit->shellparam.p[left];
     138        psh->shellparam.p[left] = savestr(psh, arg);
     139    }
     140
     141    /* The shellparam.optnext member is either NULL or points to a 'p' entry. */
     142    if (inherit->shellparam.optnext) {
     143        size_t idx = (size_t)(inherit->shellparam.optnext - inherit->shellparam.p);
     144        assert(idx <= inherit->shellparam.nparam);
     145        if (idx <= inherit->shellparam.nparam)
     146            psh->shellparam.optnext = &psh->shellparam.p[idx];
     147    }
     148
     149    /* The shellparam.optptr member is either NULL or points within argument
     150       prior to shellparam.optnext.  We can leave it as NULL if at the EOS. */
     151    if (inherit->shellparam.optptr && *inherit->shellparam.optptr != '\0') {
     152        intptr_t idx;
     153        if (!inherit->shellparam.optnext || inherit->shellparam.optnext == inherit->shellparam.p)
     154            idx = (intptr_t)(inherit->shellparam.nparam - 1);
     155        else {
     156            idx = (intptr_t)(inherit->shellparam.optnext - inherit->shellparam.p - 1);
     157            if (idx > inherit->shellparam.nparam)
     158                idx = inherit->shellparam.nparam - 1;
     159        }
     160        while (idx >= 0) {
     161            size_t arglen, off;
     162            arg = inherit->shellparam.p[idx];
     163            arglen = strlen(arg);
     164            off = (size_t)(inherit->shellparam.optptr - arg);
     165            if (off < arglen) {
     166                psh->shellparam.optptr = psh->shellparam.p[idx] + off;
     167                break;
     168            }
     169            off--;
     170        }
     171        assert(psh->shellparam.optptr != NULL);
     172    }
     173
     174    /* minusc:    only used in main.c, so not applicable to subshells. */
     175    /* optionarg: only used by callers of nextopt, so not relevant when forking subhells. */
     176}
     177#endif /* SH_FORKED_MODE */
     178
    79179
    80180/*
     
    105205        debug(psh) = 1;
    106206#endif
     207        psh->commandnamemalloc = 0;
     208        psh->arg0malloc = 0;
    107209        psh->arg0 = argv[0];
    108210        if (sflag(psh) == 0 && psh->minusc == NULL) {
  • trunk/src/kash/options.h

    r2679 r3438  
    130130/*extern char *optptr;*/                /* used by nextopt */
    131131
     132#ifndef SH_FORKED_MODE
     133void subshellinitoptions(struct shinstance *, struct shinstance *);
     134#endif
    132135void procargs(struct shinstance *, int, char **);
    133136void optschanged(struct shinstance *);
  • trunk/src/kash/output.c

    r2290 r3438  
    356356                        f++;
    357357                }
     358#ifdef _MSC_VER  /* for SHPID_PRI / KI64_PRI */
     359                else if (*f == 'I' && f[1] == '6' && f[2] == '4') {
     360                        isquad++;
     361                        f += 3;
     362                }
     363#endif
    358364                digit = digit_upper;
    359365                switch (*f) {
  • trunk/src/kash/parser.c

    r3437 r3438  
    617617
    618618void fixredir(shinstance *psh, union node *n, const char *text, int err)
    619         {
     619{
    620620        TRACE((psh, "Fix redir %s %d\n", text, err));
    621621        if (!err)
  • trunk/src/kash/redir.c

    r3437 r3438  
    288288                args.pip[1] = pip[1];
    289289                args.len = len;
    290                 forkshell2(psh, (struct job *)NULL, (union node *)NULL, FORK_NOJOB,
     290                forkshell2(psh, (struct job *)NULL, (union node *)NULL,
     291                           FORK_NOJOB | FORK_JUST_IO,
    291292                           openhere_child, redir, &args, sizeof(args), NULL);
    292293        }
  • trunk/src/kash/shell.h

    r3062 r3438  
    9494#include "shtypes.h"
    9595
     96#ifndef SH_FORKED_MODE
     97# ifndef KASH_USE_FORKSHELL2
     98#  define KASH_USE_FORKSHELL2
     99# endif
    96100#endif
     101
     102#endif
  • trunk/src/kash/shfile.c

    r3240 r3438  
    637637#ifdef SHFILE_IN_USE
    638638        /* Get CWD with unix slashes. */
    639         char buf[SHFILE_MAX_PATH];
    640         if (getcwd(buf, sizeof(buf)))
    641         {
    642             shfile_fix_slashes(buf);
    643 
    644             pfdtab->cwd = sh_strdup(NULL, buf);
    645             if (!inherit)
     639        if (!inherit)
     640        {
     641            char buf[SHFILE_MAX_PATH];
     642            if (getcwd(buf, sizeof(buf)))
     643            {
     644                shfile_fix_slashes(buf);
     645                pfdtab->cwd = sh_strdup(NULL, buf);
     646            }
     647            if (pfdtab->cwd)
    646648            {
    647649# if K_OS == K_OS_WINDOWS
     
    817819            }
    818820            else
     821                rc = -1;
     822        }
     823        else
     824        {
     825            /*
     826             * Inherit from parent shell's file table.
     827             */
     828            shfile const *src;
     829            shfile       *dst;
     830            shmtxtmp      tmp;
     831            unsigned      fdcount;
     832            unsigned      fd;
     833
     834            shmtx_enter(&inherit->mtx, &tmp);
     835
     836            /* allocate table and cwd: */
     837            fdcount = inherit->size;
     838            pfdtab->tab = dst = (shfile *)(fdcount ? sh_calloc(NULL, sizeof(pfdtab->tab[0]), fdcount) : NULL);
     839            pfdtab->cwd = sh_strdup(NULL, inherit->cwd);
     840            if (   pfdtab->cwd
     841                && (pfdtab->tab || fdcount == 0))
    819842            {
    820                 /** @todo */
    821                 errno = ENOSYS;
     843                /* duplicate table entries: */
     844                for (fd = 0, src = inherit->tab; fd < fdcount; fd++, src++, dst++)
     845                    if (src->fd == -1)
     846                        dst->native = dst->fd = -1;
     847                    else
     848                    {
     849# ifdef SH_FORKED_MODE
     850                        KBOOL const cox = !!(src->shflags & SHFILE_FLAGS_CLOSE_ON_EXEC);
     851# else
     852                        KBOOL const cox = !!(src->shflags & SHFILE_FLAGS_CLOSE_ON_EXEC); /// @todo K_TRUE
     853# endif
     854                        *dst = *src;
     855# if K_OS == K_OS_WINDOWS
     856                        if (DuplicateHandle(GetCurrentProcess(),
     857                                            (HANDLE)src->native,
     858                                            GetCurrentProcess(),
     859                                            (HANDLE *)&dst->native,
     860                                            0,
     861                                            cox ? FALSE : TRUE /* bInheritHandle */,
     862                                            DUPLICATE_SAME_ACCESS))
     863                            TRACE2((NULL, "shfile_init: %d (%#x, %#x) %p (was %p)\n",
     864                                    dst->fd, dst->oflags, dst->shflags, dst->native, src->native));
     865                        else
     866                        {
     867                            dst->native = (intptr_t)INVALID_HANDLE_VALUE;
     868                            rc = shfile_dos2errno(GetLastError());
     869                            TRACE2((NULL, "shfile_init: %d (%#x, %#x) %p - failed %d / %u!\n",
     870                                    dst->fd, dst->oflags, dst->shflags, src->native, rc, GetLastError()));
     871                            break;
     872                        }
     873
     874# elif K_OS == K_OS_LINUX /* 2.6.27 / glibc 2.9 */ || K_OS == K_OS_FREEBSD /* 10.0 */ || K_OS == K_OS_NETBSD /* 6.0 */
     875                        dst->native = dup3(src->native, -1, cox ? O_CLOEXEC : 0);
     876# else
     877                        if (cox)
     878                        {
     879#  ifndef SH_FORKED_MODE
     880                            shmtxtmp tmp2;
     881                            shmtx_enter(&global_exec_something, &tmp)
     882#  endif
     883                            dst->native = dup2(src->native, -1);
     884                            if (dst->native >= 0)
     885                                rc = fcntl(dst->native, F_SETFD, FD_CLOEXEC);
     886#  ifndef SH_FORKED_MODE
     887                            shmtx_leave(&global_exec_something, &tmp)
     888#  endif
     889                            if (rc != 0)
     890                                break;
     891                        }
     892                        else
     893                            dst->native = dup2(src->native, -1);
     894                        if (dst->native < 0)
     895                        {
     896                            rc = -1;
     897                            break;
     898                        }
     899# endif
     900                    }
     901            }
     902            else
    822903                rc = -1;
    823             }
    824         }
    825         else
    826             rc = -1;
     904            pfdtab->size = fd;
     905            shmtx_leave(&inherit->mtx, &tmp);
     906        }   /* inherit != NULL */
    827907#endif
    828908    }
     
    833913
    834914/**
    835  * Changes the inheritability of a file descriptro, taking console handles into
     915 * Changes the inheritability of a file descriptor, taking console handles into
    836916 * account.
    837917 *
  • trunk/src/kash/shfork-win.c

    r2416 r3438  
    246246                if (ResumeThread(ProcInfo.hThread) != (DWORD)-1)
    247247                {
    248                     rc = sh_add_child(psh, ProcInfo.dwProcessId, ProcInfo.hProcess);
     248                    rc = sh_add_child(psh, ProcInfo.dwProcessId, ProcInfo.hProcess, K_TRUE);
    249249                    if (!rc)
    250250                        rc = (int)ProcInfo.dwProcessId;
  • trunk/src/kash/shheap.c

    r2416 r3438  
    3535#include "shinstance.h"
    3636
    37 #if K_OS == K_OS_WINDOWS
     37#if K_OS == K_OS_WINDOWS && defined(SH_FORKED_MODE)
    3838# define SHHEAP_IN_USE
    3939#endif
  • trunk/src/kash/shinstance.c

    r3437 r3438  
    4040#include "shinstance.h"
    4141
     42#include "alias.h"
     43#include "memalloc.h"
     44#include "shell.h"
     45#include "trap.h"
     46
    4247#if K_OS == K_OS_WINDOWS
    4348# include <Windows.h>
     49# ifdef SH_FORKED_MODE
    4450extern pid_t shfork_do(shinstance *psh); /* shforkA-win.asm */
     51# endif
    4552#endif
    4653
     
    174181static void sh_destroy(shinstance *psh)
    175182{
     183/** @todo finish this...   */
    176184    memset(psh, 0, sizeof(*psh));
    177185    sh_free(NULL, psh);
     
    221229
    222230/**
    223  * Creates a root shell instance.
    224  *
    225  * @param   inherit     The shell to inherit from. If NULL inherit from environment and such.
    226  * @param   argc        The argument count.
     231 * Creates a shell instance, caller must link it.
     232 *
     233 * @param   inherit     The shell to inherit from, or NULL if root.
    227234 * @param   argv        The argument vector.
    228235 * @param   envp        The environment vector.
     236 * @param   parentfdtab File table to inherit from, NULL if root.
    229237 *
    230238 * @returns pointer to root shell on success, NULL on failure.
    231239 */
    232 shinstance *sh_create_root_shell(shinstance *inherit, int argc, char **argv, char **envp)
     240static shinstance *sh_create_shell_common(char **argv, char **envp, shfdtab *parentfdtab)
    233241{
    234242    shinstance *psh;
    235     int i;
    236243
    237244    /*
     
    241248    if (psh)
    242249    {
    243         /* Init it enough for sh_destroy() to not get upset */
    244           /* ... */
     250        /* Init it enough for sh_destroy() to not get upset: */
     251        /* ... */
    245252
    246253        /* Call the basic initializers. */
    247254        if (    !sh_clone_string_vector(psh, &psh->shenviron, envp)
    248             &&  !sh_clone_string_vector(psh, &psh->argptr, argv)
    249             &&  !shfile_init(&psh->fdtab, inherit ? &inherit->fdtab : NULL))
    250         {
    251             /* the special stuff. */
    252 #ifdef _MSC_VER
    253             psh->pid = _getpid();
     255            &&  !sh_clone_string_vector(psh, &psh->orgargv, argv)
     256            &&  !shfile_init(&psh->fdtab, parentfdtab))
     257        {
     258            unsigned i;
     259
     260            /*
     261             * The special stuff.
     262             */
     263#ifdef _MSC_VER
     264            psh->pgid = psh->pid = _getpid();
    254265#else
    255266            psh->pid = getpid();
    256 #endif
     267            psh->pgid = getpgid();
     268#endif
     269
    257270            /*sh_sigemptyset(&psh->sigrestartset);*/
    258             for (i = 0; i < NSIG; i++)
     271            for (i = 0; i < K_ELEMENTS(psh->sigactions); i++)
    259272                psh->sigactions[i].sh_handler = SH_SIG_UNK;
    260             if (inherit)
    261                 psh->sigmask = psh->sigmask;
    262             else
    263             {
    264273#if defined(_MSC_VER)
    265                 sh_sigemptyset(&psh->sigmask);
    266 #else
    267                 sigprocmask(SIG_SETMASK, NULL, &psh->sigmask);
    268 #endif
    269             }
     274            sh_sigemptyset(&psh->sigmask);
     275#else
     276            sigprocmask(SIG_SETMASK, NULL, &psh->sigmask);
     277#endif
     278
     279            /*
     280             * State initialization.
     281             */
     282            /* cd.c */
     283            psh->getpwd_first = 1;
     284
     285            /* exec */
     286            psh->builtinloc = -1;
    270287
    271288            /* memalloc.c */
     
    303320            /* show.c */
    304321            psh->tracefd = -1;
    305 
    306             /* link it. */
    307             sh_int_link(psh);
    308322            return psh;
    309323        }
     
    313327    return NULL;
    314328}
     329
     330/**
     331 * Creates the root shell instance.
     332 *
     333 * @param   argv        The argument vector.
     334 * @param   envp        The environment vector.
     335 *
     336 * @returns pointer to root shell on success, NULL on failure.
     337 */
     338shinstance *sh_create_root_shell(char **argv, char **envp)
     339{
     340    shinstance *psh = sh_create_shell_common(argv, envp, NULL /*parentfdtab*/);
     341    if (psh)
     342    {
     343        sh_int_link(psh);
     344        return psh;
     345    }
     346    return NULL;
     347}
     348
     349#ifndef SH_FORKED_MODE
     350
     351/**
     352 * Does the inherting from the parent shell instance.
     353 */
     354static void sh_inherit_from_parent(shinstance *psh, shinstance *inherit)
     355{
     356    /*
     357     * Do the rest of the inheriting.
     358     */
     359    psh->parent = inherit;
     360    psh->pgid = inherit->pgid;
     361
     362    psh->sigmask = psh->sigmask;
     363    /** @todo sigactions?   */
     364    /// @todo suppressint?
     365
     366    /* alises: */
     367    subshellinitalias(psh, inherit);
     368
     369    /* cd.c */
     370    psh->getpwd_first = inherit->getpwd_first;
     371    if (inherit->curdir)
     372        psh->curdir = savestr(psh, inherit->curdir);
     373    if (inherit->prevdir)
     374        psh->prevdir = savestr(psh, inherit->prevdir);
     375
     376    /* eval.h */
     377    /* psh->commandname - see subshellinitoptions */
     378    psh->exitstatus  = inherit->exitstatus;          /// @todo ??
     379    psh->back_exitstatus = inherit->back_exitstatus; /// @todo ??
     380    psh->funcnest = inherit->funcnest;
     381    psh->evalskip = inherit->evalskip;               /// @todo ??
     382    psh->skipcount = inherit->skipcount;             /// @todo ??
     383
     384    /* exec.c */
     385    subshellinitexec(psh, inherit);
     386
     387    /* input.h/input.c - only for the parser and anyway forkchild calls closescript(). */
     388
     389    /* jobs.h - should backgndpid be -1 in subshells? */
     390
     391    /* jobs.c -    */
     392    psh->jobctl = inherit->jobctl;  /// @todo ??
     393    psh->initialpgrp = inherit->initialpgrp;
     394    psh->ttyfd = inherit->ttyfd;
     395    /** @todo copy jobtab so the 'jobs' command can be run in a subshell.
     396     *  Better, make it follow the parent chain and skip the copying.  Will
     397     *  require some kind of job locking. */
     398
     399    /* mail.c - nothing (for now at least) */
     400
     401    /* main.h */
     402    psh->rootpid = inherit->rootpid;
     403    psh->psh_rootshell = inherit->psh_rootshell;
     404
     405    /* memalloc.h / memalloc.c - nothing. */
     406
     407    /* myhistedit.h  */ /** @todo copy history? Do we need to care? */
     408
     409    /* output.h */ /** @todo not sure this is possible/relevant for subshells */
     410    psh->output.fd = inherit->output.fd;
     411    psh->errout.fd = inherit->errout.fd;
     412    if (inherit->out1 == &inherit->memout)
     413        psh->out1 = &psh->memout;
     414    if (inherit->out2 == &inherit->memout)
     415        psh->out2 = &psh->memout;
     416
     417    /* options.h */
     418    subshellinitoptions(psh, inherit);
     419
     420    /* parse.h/parse.c */
     421    psh->whichprompt = inherit->whichprompt;
     422    /* tokpushback, doprompt and needprompt shouldn't really matter, parsecmd resets thems. */
     423    /* The rest are internal to the parser, as I see them, and can be ignored. */
     424
     425    /* redir.c - we shouldn't sub-shell with redirlist as non-NULL, I think.  */
     426    assert(inherit->redirlist == NULL);
     427    assert(inherit->fd0_redirected == 0); /* (follows from redirlist == NULL) */
     428
     429    /* show.c */
     430    psh->tracefd = inherit->tracefd;
     431
     432    /* trap.h / trap.c */ /** @todo we don't carry pendingsigs to the subshell, right? */
     433    subshellinittrap(psh, inherit);
     434
     435    /* var.h */
     436    subshellinitvar(psh, inherit);
     437}
     438
     439/**
     440 * Creates a child shell instance.
     441 *
     442 * @param   inherit     The shell to inherit from.
     443 *
     444 * @returns pointer to root shell on success, NULL on failure.
     445 */
     446shinstance *sh_create_child_shell(shinstance *inherit)
     447{
     448    shinstance *psh = sh_create_shell_common(inherit->orgargv, inherit->shenviron, &inherit->fdtab);
     449    if (psh)
     450    {
     451        /* Fake a pid for the child: */
     452        static unsigned volatile s_cShells = 0;
     453        int const iSubShell = ++s_cShells;
     454        psh->pid = SHPID_MAKE(SHPID_GET_PID(inherit->pid), iSubShell);
     455
     456        sh_inherit_from_parent(psh, inherit);
     457
     458        /* link it */
     459        sh_int_link(psh);
     460        return psh;
     461    }
     462    return NULL;
     463}
     464
     465#endif /* !SH_FORKED_MODE */
    315466
    316467/** getenv() */
     
    777928}
    778929
    779 int sh_kill(shinstance *psh, pid_t pid, int signo)
     930int sh_kill(shinstance *psh, shpid pid, int signo)
    780931{
    781932    shinstance *pshDst;
     
    793944        if (pshDst->pid == pid)
    794945        {
    795             TRACE2((psh, "sh_kill(%d, %d): pshDst=%p\n", pid, signo, pshDst));
     946            TRACE2((psh, "sh_kill(%" SHPID_PRI ", %d): pshDst=%p\n", pid, signo, pshDst));
    796947            sh_sig_do_signal(psh, pshDst, signo, 1 /* locked */);
    797948
     
    807958     * Some other process, call kill where possible
    808959     */
    809 #if defined(SH_FORKED_MODE)
    810 # ifdef _MSC_VER
     960#ifdef _MSC_VER
    811961    errno = ENOSYS;
    812962    rc = -1;
    813 # else
     963#elif defined(SH_FORKED_MODE)
    814964/*    fprintf(stderr, "kill(%d, %d)\n", pid, signo);*/
    815965    rc = kill(pid, signo);
    816 # endif
    817 
    818 #else
     966#else
     967# error "PORT ME?"
    819968#endif
    820969
     
    823972}
    824973
    825 int sh_killpg(shinstance *psh, pid_t pgid, int signo)
    826 {
     974int sh_killpg(shinstance *psh, shpid pgid, int signo)
     975{
     976    shinstance *pshDst;
     977    shmtxtmp tmp;
    827978    int rc;
    828979
    829 #if defined(SH_FORKED_MODE)
    830 # ifdef _MSC_VER
     980    /*
     981     * Self or any of the subshells?
     982     */
     983    shmtx_enter(&g_sh_mtx, &tmp);
     984
     985    pshDst = g_sh_tail;
     986    while (pshDst != NULL)
     987    {
     988        if (pshDst->pgid == pgid)
     989        {
     990            TRACE2((psh, "sh_killpg(%" SHPID_PRI ", %d): pshDst=%p\n", pgid, signo, pshDst));
     991            sh_sig_do_signal(psh, pshDst, signo, 1 /* locked */);
     992
     993            shmtx_leave(&g_sh_mtx, &tmp);
     994            return 0;
     995        }
     996        pshDst = pshDst->prev;
     997    }
     998
     999    shmtx_leave(&g_sh_mtx, &tmp);
     1000
     1001#ifdef _MSC_VER
    8311002    errno = ENOSYS;
    8321003    rc = -1;
    833 # else
     1004#elif defined(SH_FORKED_MODE)
    8341005    //fprintf(stderr, "killpg(%d, %d)\n", pgid, signo);
    8351006    rc = killpg(pgid, signo);
    836 # endif
    837 
    838 #else
    839 #endif
    840 
    841     TRACE2((psh, "sh_killpg(%d, %d) -> %d [%d]\n", pgid, signo, rc, errno));
     1007#else
     1008# error "PORTME?"
     1009#endif
     1010
     1011    TRACE2((psh, "sh_killpg(%" SHPID_PRI ", %d) -> %d [%d]\n", pgid, signo, rc, errno));
    8421012    (void)psh;
    8431013    return rc;
     
    8461016clock_t sh_times(shinstance *psh, shtms *tmsp)
    8471017{
    848 #if defined(SH_FORKED_MODE)
    849     (void)psh;
    850 # ifdef _MSC_VER
     1018#ifdef _MSC_VER
    8511019    errno = ENOSYS;
    8521020    return (clock_t)-1;
    853 # else
     1021#elif defined(SH_FORKED_MODE)
     1022    (void)psh;
    8541023    return times(tmsp);
    855 # endif
    856 
    857 #else
     1024#else
     1025# error "PORTME"
    8581026#endif
    8591027}
     
    8731041 * @returns 0 on success, on failure -1 and errno set to ENOMEM.
    8741042 *
    875  * @param   psh     The shell instance.
    876  * @param   pid     The child pid.
    877  * @param   hChild  Windows child handle.
     1043 * @param   psh         The shell instance.
     1044 * @param   pid         The child pid.
     1045 * @param   hChild      Windows child handle.
     1046 * @param   fProcess    Set if process, clear if thread.
    8781047 */
    879 int sh_add_child(shinstance *psh, pid_t pid, void *hChild)
     1048int sh_add_child(shinstance *psh, shpid pid, void *hChild, KBOOL fProcess)
    8801049{
    8811050    /* get a free table entry. */
     
    8981067    psh->children[i].hChild = hChild;
    8991068#endif
    900     (void)hChild;
     1069#ifndef SH_FORKED_MODE
     1070    psh->children[i].fProcess = fProcess;
     1071#endif
     1072    (void)hChild; (void)fProcess;
    9011073    return 0;
    9021074}
     1075
     1076#ifdef SH_FORKED_MODE
    9031077
    9041078pid_t sh_fork(shinstance *psh)
     
    9381112}
    9391113
     1114#else  /* !SH_FORKED_MODE */
     1115
     1116# ifdef _MSC_VER
     1117/** Thread wrapper procedure. */
     1118static unsigned __stdcall sh_thread_wrapper(void *user)
     1119{
     1120    shinstance *psh = (shinstance *)user;
     1121    int iExit;
     1122
     1123    /* Update the TID and PID (racing sh_thread_start) */
     1124    DWORD tid = GetCurrentThreadId();
     1125    shpid pid = GetCurrentProcessId();
     1126
     1127    pid = SHPID_MAKE(pid, tid);
     1128    psh->pid = pid;
     1129    psh->tid = tid;
     1130
     1131    /* Set the TLS entry before we try TRACE or TRACE2. */
     1132    shthread_set_shell(psh);
     1133
     1134    TRACE2((psh, "sh_thread_wrapper: enter\n"));
     1135    iExit = psh->thread(psh, psh->threadarg);
     1136/** @todo do shell cleanup. */
     1137    TRACE2((psh, "sh_thread_wrapper: quits - iExit=%d\n", iExit));
     1138
     1139    _endthreadex(iExit);
     1140    return iExit;
     1141}
     1142# else
     1143#  error "PORTME"
     1144# endif
     1145
     1146/**
     1147 * Starts a sub-shell thread.
     1148 */
     1149shpid sh_thread_start(shinstance *pshparent, shinstance *pshchild, int (*thread)(shinstance *, void *), void *arg)
     1150{
     1151# ifdef _MSC_VER
     1152    unsigned tid = 0;
     1153    uintptr_t hThread;
     1154    shpid pid;
     1155
     1156    pshchild->thread    = thread;
     1157    pshchild->threadarg = arg;
     1158    hThread = _beginthreadex(NULL /*security*/, 0 /*stack_size*/, sh_thread_wrapper, pshchild, 0 /*initflags*/, &tid);
     1159    if (hThread == -1)
     1160        return -errno;
     1161
     1162    pid = SHPID_MAKE(SHPID_GET_PID(pshparent->pid), tid);
     1163    pshchild->pid = pid;
     1164    pshchild->tid = tid;
     1165
     1166    if (sh_add_child(pshparent, pid, (void *)hThread, K_FALSE) != 0) {
     1167        return -ENOMEM;
     1168    }
     1169    return pid;
     1170
     1171# else
     1172#  error "PORTME"
     1173# endif
     1174}
     1175
     1176#endif /* !SH_FORKED_MODE */
     1177
    9401178/** waitpid() */
    941 pid_t sh_waitpid(shinstance *psh, pid_t pid, int *statusp, int flags)
    942 {
    943     pid_t pidret;
     1179shpid sh_waitpid(shinstance *psh, shpid pid, int *statusp, int flags)
     1180{
     1181    shpid  pidret;
    9441182#if K_OS == K_OS_WINDOWS //&& defined(SH_FORKED_MODE)
    9451183    DWORD   dwRet;
     
    10151253        {
    10161254            DWORD dwExitCode = 127;
     1255#ifndef SH_FORKED_MODE
     1256            if (psh->children[i].fProcess ? GetExitCodeProcess(hChild, &dwExitCode) : GetExitCodeThread(hChild, &dwExitCode))
     1257#else
    10171258            if (GetExitCodeProcess(hChild, &dwExitCode))
     1259#endif
    10181260            {
    10191261                pidret = psh->children[i].pid;
     
    10461288#endif
    10471289
    1048     TRACE2((psh, "waitpid(%d, %p, %#x) -> %d [%d] *statusp=%#x (rc=%d)\n", pid, statusp, flags,
     1290    TRACE2((psh, "waitpid(%" SHPID_PRI ", %p, %#x) -> %" SHPID_PRI " [%d] *statusp=%#x (rc=%d)\n", pid, statusp, flags,
    10491291            pidret, errno, *statusp, WEXITSTATUS(*statusp)));
    10501292    (void)psh;
     
    12821524uid_t sh_getuid(shinstance *psh)
    12831525{
    1284 #if defined(SH_FORKED_MODE)
    1285 # ifdef _MSC_VER
     1526#ifdef _MSC_VER
    12861527    uid_t uid = 0;
    1287 # else
     1528#else
    12881529    uid_t uid = getuid();
    1289 # endif
    1290 
    1291 #else
    12921530#endif
    12931531
     
    12991537uid_t sh_geteuid(shinstance *psh)
    13001538{
    1301 #if defined(SH_FORKED_MODE)
    1302 # ifdef _MSC_VER
     1539#ifdef _MSC_VER
    13031540    uid_t euid = 0;
    1304 # else
     1541#else
    13051542    uid_t euid = geteuid();
    1306 # endif
    1307 
    1308 #else
    13091543#endif
    13101544
     
    13161550gid_t sh_getgid(shinstance *psh)
    13171551{
    1318 #if defined(SH_FORKED_MODE)
    1319 # ifdef _MSC_VER
     1552#ifdef _MSC_VER
    13201553    gid_t gid = 0;
    1321 # else
     1554#else
    13221555    gid_t gid = getgid();
    1323 # endif
    1324 
    1325 #else
    13261556#endif
    13271557
     
    13331563gid_t sh_getegid(shinstance *psh)
    13341564{
    1335 #if defined(SH_FORKED_MODE)
    1336 # ifdef _MSC_VER
     1565#ifdef _MSC_VER
    13371566    gid_t egid = 0;
    1338 # else
     1567#else
    13391568    gid_t egid = getegid();
    1340 # endif
    1341 
    1342 #else
    13431569#endif
    13441570
     
    13481574}
    13491575
    1350 pid_t sh_getpid(shinstance *psh)
    1351 {
    1352     pid_t pid;
    1353 
    1354 #if defined(SH_FORKED_MODE)
    1355 # ifdef _MSC_VER
    1356     pid = _getpid();
    1357 # else
    1358     pid = getpid();
    1359 # endif
    1360 #else
    1361 #endif
    1362 
     1576shpid sh_getpid(shinstance *psh)
     1577{
     1578    return psh->pid;
     1579}
     1580
     1581shpid sh_getpgrp(shinstance *psh)
     1582{
     1583    shpid pgid = psh->pgid;
     1584#ifndef _MSC_VER
     1585    assert(pgid == getpgrp());
     1586#endif
     1587
     1588    TRACE2((psh, "sh_getpgrp() -> %" SHPID_PRI " [%d]\n", pgid, errno));
     1589    return pgid;
     1590}
     1591
     1592/**
     1593 * @param   pid     Should always be zero, i.e. referring to the current shell
     1594 *                  process.
     1595 */
     1596shpid sh_getpgid(shinstance *psh, shpid pid)
     1597{
     1598    shpid pgid;
     1599    if (pid == 0 || psh->pid == pid)
     1600    {
     1601        shpid pgid = psh->pgid;
     1602#ifndef _MSC_VER
     1603        assert(pgid == getpgrp());
     1604#endif
     1605    }
     1606    else
     1607    {
     1608        assert(0);
     1609        errno = ESRCH;
     1610        pgid = -1;
     1611    }
     1612
     1613    TRACE2((psh, "sh_getpgid(%" SHPID_PRI ") -> %" SHPID_PRI " [%d]\n", pid, pgid, errno));
     1614    return pgid;
     1615}
     1616
     1617/**
     1618 *
     1619 * @param   pid     The pid to modify.  This is always 0, except when forkparent
     1620 *                  calls to group a newly created child.  Though, we might
     1621 *                  almost safely ignore it in that case as the child will also
     1622 *                  perform the operation.
     1623 * @param   pgid    The process group to assign @a pid to.
     1624 */
     1625int sh_setpgid(shinstance *psh, shpid pid, shpid pgid)
     1626{
     1627#if defined(SH_FORKED_MODE) && !defined(_MSC_VER)
     1628    int rc = setpgid(pid, pgid);
     1629    TRACE2((psh, "sh_setpgid(%" SHPID_PRI ", %" SHPID_PRI ") -> %d [%d]\n", pid, pgid, rc, errno));
    13631630    (void)psh;
    1364     return pid;
    1365 }
    1366 
    1367 pid_t sh_getpgrp(shinstance *psh)
    1368 {
    1369 #if defined(SH_FORKED_MODE)
    1370 # ifdef _MSC_VER
    1371     pid_t pgrp = _getpid();
    1372 # else
    1373     pid_t pgrp = getpgrp();
    1374 # endif
    1375 
    1376 #else
    1377 #endif
    1378 
    1379     TRACE2((psh, "sh_getpgrp() -> %d [%d]\n", pgrp, errno));
     1631#else
     1632    int rc = 0;
     1633    if (pid == 0 || psh->pid == pid)
     1634    {
     1635        TRACE2((psh, "sh_setpgid(self,): %" SHPID_PRI " -> %" SHPID_PRI "\n", psh->pgid, pgid));
     1636        psh->pgid = pgid;
     1637    }
     1638    else
     1639    {
     1640        /** @todo fixme   */
     1641        rc = -1;
     1642        errno = ENOSYS;
     1643    }
     1644#endif
     1645    return rc;
     1646}
     1647
     1648shpid sh_tcgetpgrp(shinstance *psh, int fd)
     1649{
     1650    shpid pgrp;
     1651
     1652#ifdef _MSC_VER
     1653    pgrp = -1;
     1654    errno = ENOSYS;
     1655#elif defined(SH_FORKED_MODE)
     1656    pgrp = tcgetpgrp(fd);
     1657#else
     1658# error "PORT ME"
     1659#endif
     1660
     1661    TRACE2((psh, "sh_tcgetpgrp(%d) -> %" SHPID_PRI " [%d]\n", fd, pgrp, errno));
    13801662    (void)psh;
    13811663    return pgrp;
    13821664}
    13831665
    1384 pid_t sh_getpgid(shinstance *psh, pid_t pid)
    1385 {
    1386 #if defined(SH_FORKED_MODE)
    1387 # ifdef _MSC_VER
    1388     pid_t pgid = pid;
    1389 # else
    1390     pid_t pgid = getpgid(pid);
    1391 # endif
    1392 
    1393 #else
    1394 #endif
    1395 
    1396     TRACE2((psh, "sh_getpgid(%d) -> %d [%d]\n", pid, pgid, errno));
     1666int sh_tcsetpgrp(shinstance *psh, int fd, shpid pgrp)
     1667{
     1668    int rc;
     1669    TRACE2((psh, "sh_tcsetpgrp(%d, %" SHPID_PRI ")\n", fd, pgrp));
     1670
     1671#ifdef _MSC_VER
     1672    rc = -1;
     1673    errno = ENOSYS;
     1674#elif defined(SH_FORKED_MODE)
     1675    rc = tcsetpgrp(fd, pgrp);
     1676#else
     1677# error "PORT ME"
     1678#endif
     1679
     1680    TRACE2((psh, "sh_tcsetpgrp(%d, %" SHPID_PRI ") -> %d [%d]\n", fd, pgrp, rc, errno));
    13971681    (void)psh;
    1398     return pgid;
    1399 }
    1400 
    1401 int sh_setpgid(shinstance *psh, pid_t pid, pid_t pgid)
    1402 {
    1403 #if defined(SH_FORKED_MODE)
    1404 # ifdef _MSC_VER
     1682    return rc;
     1683}
     1684
     1685int sh_getrlimit(shinstance *psh, int resid, shrlimit *limp)
     1686{
     1687#ifdef _MSC_VER
    14051688    int rc = -1;
    14061689    errno = ENOSYS;
    1407 # else
    1408     int rc = setpgid(pid, pgid);
    1409 # endif
    1410 
    1411 #else
    1412 #endif
    1413 
    1414     TRACE2((psh, "sh_setpgid(%d, %d) -> %d [%d]\n", pid, pgid, rc, errno));
    1415     (void)psh;
    1416     return rc;
    1417 }
    1418 
    1419 pid_t sh_tcgetpgrp(shinstance *psh, int fd)
    1420 {
    1421     pid_t pgrp;
    1422 
    1423 #if defined(SH_FORKED_MODE)
    1424 # ifdef _MSC_VER
    1425     pgrp = -1;
    1426     errno = ENOSYS;
    1427 # else
    1428     pgrp = tcgetpgrp(fd);
    1429 # endif
    1430 
    1431 #else
    1432 #endif
    1433 
    1434     TRACE2((psh, "sh_tcgetpgrp(%d) -> %d [%d]\n", fd, pgrp, errno));
    1435     (void)psh;
    1436     return pgrp;
    1437 }
    1438 
    1439 int sh_tcsetpgrp(shinstance *psh, int fd, pid_t pgrp)
    1440 {
    1441     int rc;
    1442     TRACE2((psh, "sh_tcsetpgrp(%d, %d)\n", fd, pgrp));
    1443 
    1444 #if defined(SH_FORKED_MODE)
    1445 # ifdef _MSC_VER
    1446     rc = -1;
    1447     errno = ENOSYS;
    1448 # else
    1449     rc = tcsetpgrp(fd, pgrp);
    1450 # endif
    1451 
    1452 #else
    1453 #endif
    1454 
    1455     TRACE2((psh, "sh_tcsetpgrp(%d, %d) -> %d [%d]\n", fd, pgrp, rc, errno));
    1456     (void)psh;
    1457     return rc;
    1458 }
    1459 
    1460 int sh_getrlimit(shinstance *psh, int resid, shrlimit *limp)
    1461 {
    1462 #if defined(SH_FORKED_MODE)
    1463 # ifdef _MSC_VER
    1464     int rc = -1;
    1465     errno = ENOSYS;
    1466 # else
     1690#elif defined(SH_FORKED_MODE)
    14671691    int rc = getrlimit(resid, limp);
    1468 # endif
    1469 
    1470 #else
     1692#else
     1693# error "PORT ME"
    14711694    /* returned the stored limit */
    14721695#endif
     
    14801703int sh_setrlimit(shinstance *psh, int resid, const shrlimit *limp)
    14811704{
    1482 #if defined(SH_FORKED_MODE)
    1483 # ifdef _MSC_VER
     1705#ifdef _MSC_VER
    14841706    int rc = -1;
    14851707    errno = ENOSYS;
    1486 # else
     1708#elif defined(SH_FORKED_MODE)
    14871709    int rc = setrlimit(resid, limp);
    1488 # endif
    1489 
    1490 #else
     1710#else
     1711# error "PORT ME"
    14911712    /* if max(shell) < limp; then setrlimit; fi
    14921713       if success; then store limit for later retrival and maxing. */
  • trunk/src/kash/shinstance.h

    r3435 r3438  
    6565typedef struct shchild
    6666{
    67     pid_t       pid;                    /**< The pid. */
     67    shpid       pid;                    /**< The pid. */
    6868#if K_OS == K_OS_WINDOWS
    6969    void       *hChild;                 /**< The process handle. */
     70#endif
     71#ifndef SH_FORKED_MODE
     72    KBOOL       fProcess;               /**< Set if process, clear if internal thread. */
    7073#endif
    7174} shchild;
     
    140143    struct shinstance  *prev;           /**< The previous shell instance. */
    141144    struct shinstance  *parent;         /**< The parent shell instance. */
    142     pid_t               pid;            /**< The (fake) process id of this shell instance. */
     145    shpid               pid;            /**< The (fake) process id of this shell instance. */
    143146    shtid               tid;            /**< The thread identifier of the thread for this shell. */
     147    shpid               pgid;           /**< Process group ID. */
    144148    shfdtab             fdtab;          /**< The file descriptor table. */
    145149    shsigaction_t       sigactions[NSIG]; /**< The signal actions registered with this shell instance. */
     
    148152    int                 num_children;   /**< Number of children in the array. */
    149153    shchild            *children;       /**< The child array. */
     154#ifndef SH_FORKED_MODE
     155    int (*thread)(struct shinstance *, void *); /**< The thread procedure. */
     156    void               *threadarg;      /**< The thread argument. */
     157#endif
    150158
    151159    /* alias.c */
    152160#define ATABSIZE 39
    153161    struct alias       *atab[ATABSIZE];
     162    unsigned            aliases;        /**< Number of active aliases. */
    154163
    155164    /* cd.c */
     
    178187    int                 skipcount;      /**< number of levels to skip */
    179188    int                 loopnest;       /**< current loop nesting level */
     189    int                 commandnamemalloc; /**< Set if commandname is malloc'ed (only subshells). */
    180190
    181191    /* expand.c */
     
    210220
    211221    /* jobs.h */
    212     pid_t               backgndpid/* = -1 */;   /**< pid of last background process */
     222    shpid               backgndpid/* = -1 */;   /**< pid of last background process */
    213223    int                 job_warning;    /**< user was warned about stopped jobs */
    214224
     
    217227    int                 njobs;          /**< size of array */
    218228    int                 jobs_invalid;   /**< set in child */
    219     int                 initialpgrp;    /**< pgrp of shell on invocation */
     229    shpid               initialpgrp;    /**< pgrp of shell on invocation */
    220230    int                 curjob/* = -1*/;/**< current job */
    221231    int                 ttyfd/* = -1*/;
     
    231241
    232242    /* main.h */
    233     int                 rootpid;        /**< pid of main shell. */
     243    shpid               rootpid;        /**< pid of main shell. */
    234244    int                 rootshell;      /**< true if we aren't a child of the main shell. */
    235245    struct shinstance  *psh_rootshell;  /**< The root shell pointer. (!rootshell) */
     
    272282    char               *optionarg;      /**< set by nextopt */
    273283    char               *optptr;         /**< used by nextopt */
     284    char              **orgargv;        /**< The original argument vector (for cleanup). */
     285    int                 arg0malloc;     /**< Indicates whether arg0 was allocated or is part of orgargv. */
    274286
    275287    /* parse.h */
     
    346358
    347359
    348 extern shinstance *sh_create_root_shell(shinstance *, int, char **, char **);
     360extern shinstance *sh_create_root_shell(char **, char **);
     361extern shinstance *sh_create_child_shell(shinstance *);
    349362
    350363/* environment & pwd.h */
     
    395408SH_NORETURN_1 void sh_abort(shinstance *) SH_NORETURN_2;
    396409void sh_raise_sigint(shinstance *);
    397 int sh_kill(shinstance *, pid_t, int);
    398 int sh_killpg(shinstance *, pid_t, int);
     410int sh_kill(shinstance *, shpid, int);
     411int sh_killpg(shinstance *, shpid, int);
    399412
    400413/* times */
     
    416429
    417430/* wait / process */
    418 int sh_add_child(shinstance *psh, pid_t pid, void *hChild);
     431int sh_add_child(shinstance *psh, shpid pid, void *hChild, KBOOL fProcess);
    419432#ifdef _MSC_VER
    420433#   include <process.h>
     
    442455#   endif
    443456#endif
    444 pid_t sh_fork(shinstance *);
    445 pid_t sh_waitpid(shinstance *, pid_t, int *, int);
     457#ifdef SH_FORKED_MODE
     458shpid sh_fork(shinstance *);
     459#else
     460shpid sh_thread_start(shinstance *pshparent, shinstance *pshchild, int (*thread)(shinstance *, void *), void *arg);
     461#endif
     462shpid sh_waitpid(shinstance *, shpid, int *, int);
    446463SH_NORETURN_1 void sh__exit(shinstance *, int) SH_NORETURN_2;
    447464int sh_execve(shinstance *, const char *, const char * const*, const char * const *);
     
    450467gid_t sh_getgid(shinstance *);
    451468gid_t sh_getegid(shinstance *);
    452 pid_t sh_getpid(shinstance *);
    453 pid_t sh_getpgrp(shinstance *);
    454 pid_t sh_getpgid(shinstance *, pid_t);
    455 int sh_setpgid(shinstance *, pid_t, pid_t);
     469shpid sh_getpid(shinstance *);
     470shpid sh_getpgrp(shinstance *);
     471shpid sh_getpgid(shinstance *, shpid);
     472int sh_setpgid(shinstance *, shpid, shpid);
    456473
    457474/* tc* */
    458 pid_t sh_tcgetpgrp(shinstance *, int);
    459 int sh_tcsetpgrp(shinstance *, int, pid_t);
     475shpid sh_tcgetpgrp(shinstance *, int);
     476int sh_tcsetpgrp(shinstance *, int, shpid);
    460477
    461478/* sys/resource.h */
  • trunk/src/kash/show.c

    r2423 r3438  
    299299
    300300        if (pos) {
    301         int     s = errno;
     301                int     s = errno;
    302302                char    prefix[40];
    303303                size_t  len;
    304304
    305                 len = sprintf(prefix, "[%d] ", sh_getpid(psh));
     305#ifdef SH_FORKED_MODE
     306                len = sprintf(prefix, "[%" SHPID_PRI "] ", sh_getpid(psh));
     307#else
     308                shpid pid = sh_getpid(psh);
     309                len = sprintf(prefix, "[%d/%d] ", SHPID_GET_PID(pid), SHPID_GET_TID(pid));
     310#endif
    306311                shfile_write(&psh->fdtab, psh->tracefd, prefix, len);
    307312                shfile_write(&psh->fdtab, psh->tracefd, psh->tracebuf, pos);
     
    310315                psh->tracebuf[0] = '\0';
    311316
    312         errno = s;
     317                errno = s;
    313318        }
    314319}
     
    359364                } else {
    360365                        /* it's too big for some reason... */
    361             int s = errno;
     366                        int s = errno;
    362367                        trace_flush(psh);
    363368                        shfile_write(&psh->fdtab, psh->tracefd, str, len);
    364369                        if (!flush_it)
    365370                                shfile_write(&psh->fdtab, psh->tracefd, "[too long]\n", sizeof( "[too long]\n") - 1);
    366             errno = s;
     371                        errno = s;
    367372                }
    368373
  • trunk/src/kash/shtypes.h

    r2546 r3438  
    131131#endif
    132132
     133/** @name Extra wide pid_t so we can safely add a sub-pid to the top.
     134 * @{ */
     135#ifndef SH_FORKED_MODE
     136typedef KI64 shpid;
     137# define SHPID_MAKE(pid, tid)       ((shpid)(KU32)(pid) | (shpid)(KU32)(tid) << 32)
     138# define SHPID_GET_PID(shpid)       ((pid_t)(KU32)(shpid))
     139# define SHPID_GET_TID(shpid)       ((pid_t)((shpid) >> 32))
     140# define SHPID_PRI                  KI64_PRI
     141#else
     142typedef pid_t shpid;
     143# define SHPID_GET_PID(shpid)       (shpid)
     144# define SHPID_PRI                  KI32_PRI
     145#endif
     146/** @}  */
     147
    133148#endif
    134149
  • trunk/src/kash/trap.c

    r3435 r3438  
    8080static int getsigaction(shinstance *, int, shsig_t *);
    8181
     82#ifndef SH_FORKED_MODE
     83void
     84subshellinittrap(shinstance *psh, shinstance *inherit)
     85{
     86        /* The forkchild calls clear_traps(), we have to emulate that here. */
     87        unsigned i;
     88        memcpy(psh->sigmode, inherit->sigmode, sizeof(psh->sigmode));
     89        for (i = 0; i < K_ELEMENTS(inherit->trap); i++) {
     90                const char *src = inherit->trap[i];
     91                if (!src) {
     92                } else if (i > 0) {
     93                        setsignal(psh, i);
     94                }
     95        }
     96}
     97#endif
     98
     99
    82100/*
    83101 * return the signal number described by `p' (as a number or a name)
     
    210228                if (*tp && **tp) {      /* trap not NULL or SIG_IGN */
    211229                        INTOFF;
    212                         ckfree(psh, *tp);
    213                         *tp = NULL;
     230                        ckfree(psh, *tp);
     231                        *tp = NULL;
    214232                        if (tp != &psh->trap[0])
    215233                                setsignal(psh, (int)(tp - psh->trap));
     
    417435 */
    418436
    419 SH_NORETURN_1 void
    420 exitshell(shinstance *psh, int status)
     437int
     438exitshell2(shinstance *psh, int status)
    421439{
    422440        struct jmploc loc1, loc2;
    423441        char *p;
    424442
    425         TRACE((psh, "pid %d, exitshell(%d)\n", sh_getpid(psh), status));
     443        TRACE((psh, "pid %" SHPID_PRI ", exitshell(%d)\n", sh_getpid(psh), status));
    426444        if (setjmp(loc1.loc)) {
    427445                goto l1;
     
    435453                evalstring(psh, p, 0);
    436454        }
    437 l1:   psh->handler = &loc2;                     /* probably unnecessary */
     455l1:
     456        psh->handler = &loc2;                   /* probably unnecessary */
    438457        output_flushall(psh);
    439458#if JOBS
    440459        setjobctl(psh, 0);
    441460#endif
    442 l2: sh__exit(psh, status);
     461l2:
     462        return status;
     463}
     464
     465SH_NORETURN_1 void
     466exitshell(shinstance *psh, int status)
     467{
     468        sh__exit(psh, exitshell2(psh, status));
    443469        /* NOTREACHED */
    444470}
     471
  • trunk/src/kash/trap.h

    r3435 r3438  
    3737/*extern int pendingsigs;*/
    3838
     39#ifndef SH_FORKED_MODE
     40void subshellinittrap(shinstance *, shinstance *);
     41#endif
    3942int trapcmd(struct shinstance *, int, char **);
    4043void clear_traps(struct shinstance *);
     
    4447void dotrap(struct shinstance *);
    4548void setinteractive(struct shinstance *, int);
     49int exitshell2(struct shinstance *, int);
    4650SH_NORETURN_1 void exitshell(struct shinstance *, int) SH_NORETURN_2;
     51
  • trunk/src/kash/var.c

    r2641 r3438  
    4141#endif
    4242
     43#include <assert.h>
    4344#include <stddef.h>
    4445#include <stdlib.h>
     
    270271        }
    271272}
     273
     274
     275#ifndef SH_FORKED_MODE
     276/*
     277 * This routine is called to copy variable state from parent to child shell.
     278 */
     279void
     280subshellinitvar(shinstance *psh, shinstance *inherit)
     281{
     282        unsigned i;
     283        for (i = 0; i < K_ELEMENTS(inherit->vartab); i++) {
     284                struct var const *vsrc = inherit->vartab[i];
     285                if (!vsrc) {
     286                } else {
     287                        struct var **ppdst = &psh->vartab[i];
     288                        do
     289                        {
     290                                struct var *dst;
     291                                if (!(vsrc->flags & VSTRFIXED)) {
     292                                        dst = (struct var *)ckmalloc(psh, sizeof(*dst));
     293                                } else {
     294                                        /* VSTRFIXED is used when the structure is a fixed allocation in
     295                                           the shinstance structure, so scan those to find which it is: */
     296                                        size_t            left     = ((struct var *)&inherit->vartab[0] - &inherit->vatty);
     297                                        struct var const *fixedsrc = &inherit->vatty;
     298                                        dst = &psh->vatty;
     299                                        while (left-- > 0)
     300                                                if (vsrc != fixedsrc) {
     301                                                        fixedsrc++;
     302                                                        dst++;
     303                                                } else
     304                                                        break;
     305                                        assert(left < 256 /*whatever, just no rollover*/);
     306                                }
     307                                *dst = *vsrc;
     308
     309                                if (!(vsrc->flags & VTEXTFIXED)) {
     310                                        dst->text = savestr(psh, vsrc->text);
     311                                        dst->flags &= ~VSTACK;
     312                                }
     313
     314                                *ppdst = dst;
     315                                ppdst = &dst->next;
     316
     317                                vsrc = vsrc->next;
     318                        } while (vsrc);
     319                        *ppdst = NULL;
     320                }
     321        }
     322
     323        /** @todo We don't always need to copy local variables. */
     324        if (inherit->localvars) {
     325                struct localvar const *vsrc  = inherit->localvars;
     326                struct localvar      **ppdst = &psh->localvars;
     327                do
     328                {
     329                        struct localvar *dst = ckmalloc(psh, sizeof(*dst));
     330
     331                        dst->flags = vsrc->flags & ~VSTACK;
     332                        if (vsrc->flags & VTEXTFIXED)
     333                                dst->text = savestr(psh, vsrc->text);
     334                        else
     335                                dst->text = vsrc->text;
     336
     337                        dst->vp = find_var(psh, vsrc->vp->text, NULL, NULL);
     338                        assert(dst->vp);
     339
     340                        *ppdst = dst;
     341                        ppdst = &dst->next;
     342
     343                        vsrc = vsrc->next;
     344                } while (vsrc);
     345        }
     346}
     347#endif /* !SH_FORKED_MODE */
    272348
    273349/*
  • trunk/src/kash/var.h

    r2682 r3438  
    127127
    128128void initvar(struct shinstance *);
     129#ifndef SH_FORKED_MODE
     130void subshellinitvar(shinstance *, shinstance *);
     131#endif
    129132void setvar(struct shinstance *, const char *, const char *, int);
    130133void setvareq(struct shinstance *, char *, int);
Note: See TracChangeset for help on using the changeset viewer.

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