Ignore:
Timestamp:
Sep 13, 2008, 5:27:59 AM (17 years ago)
Author:
bird
Message:

kash: hacking.

File:
1 edited

Legend:

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

    r1240 r1784  
    2525 */
    2626
     27/*******************************************************************************
     28*   Header Files                                                               *
     29*******************************************************************************/
    2730#include <string.h>
    2831#include <stdlib.h>
     32#include <assert.h>
    2933#ifndef _MSC_VER
    3034# include <unistd.h>
     
    3539
    3640
     41/*******************************************************************************
     42*   Global Variables                                                           *
     43*******************************************************************************/
     44/** The mutex protecting the the globals and some shell instance members (sigs). */
     45static shmtx        g_sh_mtx;
     46/** The root shell instance. */
     47static shinstance  *g_sh_root;
     48/** The first shell instance. */
     49static shinstance  *g_sh_head;
     50/** The last shell instance. */
     51static shinstance  *g_sh_tail;
     52/** The number of shells. */
     53static int          g_num_shells;
     54/** Per signal state for determining a common denominator.
     55 * @remarks defaults and unmasked actions aren't counted. */
     56struct shsigstate
     57{
     58    /** The current signal action. */
     59#ifndef _MSC_VER
     60    struct sigaction sa;
     61#else
     62    struct
     63    {
     64        void      (*sa_handler)(int);
     65        int         sa_flags;
     66        shsigset_t  sa_mask;
     67    } sa;
     68#endif
     69    /** The number of restarts (siginterrupt / SA_RESTART). */
     70    int num_restart;
     71    /** The number of ignore handlers. */
     72    int num_ignore;
     73    /** The number of specific handlers. */
     74    int num_specific;
     75    /** The number of threads masking it. */
     76    int num_masked;
     77}                   g_sig_state[NSIG];
     78
     79
     80
     81typedef struct shmtxtmp { int i; } shmtxtmp;
     82
     83int shmtx_init(shmtx *pmtx)
     84{
     85    pmtx->b[0] = 0;
     86    return 0;
     87}
     88
     89void shmtx_delete(shmtx *pmtx)
     90{
     91    pmtx->b[0] = 0;
     92}
     93
     94void shmtx_enter(shmtx *pmtx, shmtxtmp *ptmp)
     95{
     96    pmtx->b[0] = 0;
     97    ptmp->i = 0;
     98}
     99
     100void shmtx_leave(shmtx *pmtx, shmtxtmp *ptmp)
     101{
     102    pmtx->b[0] = 0;
     103    ptmp->i = 432;
     104}
     105
     106
     107/**
     108 * Links the shell instance.
     109 *
     110 * @param   psh     The shell.
     111 */
     112static void sh_int_link(shinstance *psh)
     113{
     114    shmtxtmp tmp;
     115    shmtx_enter(&g_sh_mtx, &tmp);
     116
     117    if (psh->rootshell)
     118        g_sh_root = psh;
     119
     120    psh->next = NULL;
     121    psh->prev = g_sh_tail;
     122    if (g_sh_tail)
     123        g_sh_tail->next = psh;
     124    else
     125        g_sh_tail = g_sh_head = psh;
     126    g_sh_tail = psh;
     127
     128    g_num_shells++;
     129
     130    shmtx_leave(&g_sh_mtx, &tmp);
     131}
     132
     133
     134/**
     135 * Unlink the shell instance.
     136 *
     137 * @param   psh     The shell.
     138 */
     139static void sh_int_unlink(shinstance *psh)
     140{
     141    shmtxtmp tmp;
     142    shmtx_enter(&g_sh_mtx, &tmp);
     143
     144    g_num_shells--;
     145
     146    if (g_sh_tail == psh)
     147        g_sh_tail = psh->prev;
     148    else
     149        psh->next->prev = psh->prev;
     150
     151    if (g_sh_head == psh)
     152        g_sh_head = psh->next;
     153    else
     154        psh->prev->next = psh->next;
     155
     156    if (g_sh_root == psh)
     157        g_sh_root = 0;
     158
     159    shmtx_leave(&g_sh_mtx, &tmp);
     160}
     161
     162
    37163/**
    38164 * Creates a root shell instance.
     
    47173{
    48174    shinstance *psh;
     175    int i;
    49176
    50177    psh = calloc(sizeof(*psh), 1);
     
    57184        psh->pid = getpid();
    58185#endif
     186        /*sh_sigemptyset(&psh->sigrestartset);*/
     187        for (i = 0; i < NSIG; i++)
     188            psh->sigactions[i].sh_handler = SH_SIG_UNK;
    59189
    60190        /* memalloc.c */
     
    85215#if JOBS
    86216        psh->curjob = -1;
     217#else
     218# error asdf
    87219#endif
    88220        psh->ttyfd = -1;
     221
     222        /* link it. */
     223        sh_int_link(psh);
    89224
    90225    }
     
    98233    return NULL;
    99234#elif defined(SH_STUB_MODE)
     235    (void)psh;
    100236    return getenv(var);
    101237#else
     
    109245    return &s_null[0];
    110246#elif defined(SH_STUB_MODE)
     247    (void)psh;
    111248    return environ;
    112249#else
     
    119256    return NULL;
    120257#elif defined(SH_STUB_MODE)
     258    (void)psh;
    121259# ifdef _MSC_VER
    122260    return NULL;
     
    129267}
    130268
     269/**
     270 * Lazy initialization of a signal state, globally.
     271 *
     272 * @param   psh         The shell doing the lazy work.
     273 * @param   signo       The signal (valid).
     274 */
     275static void sh_int_lazy_init_sigaction(shinstance *psh, int signo)
     276{
     277    if (psh->sigactions[signo].sh_handler == SH_SIG_UNK)
     278    {
     279        shmtxtmp tmp;
     280        shmtx_enter(&g_sh_mtx, &tmp);
     281
     282        if (psh->sigactions[signo].sh_handler == SH_SIG_UNK)
     283        {
     284            shsigaction_t shold;
     285            shinstance *cur;
     286#ifndef _MSC_VER
     287            struct sigaction old;
     288            if (!sigaction(signo, NULL, &old))
     289            {
     290                /* convert */
     291                shold.sh_flags = old.sa_flags;
     292                shold.sh_mask = old.sa_mask;
     293                if (old.sa_handler == SIG_DFL)
     294                    shold.sh_handler = SH_SIG_DFL;
     295                else
     296                {
     297                    assert(old.sa_handler == SIG_IGN);
     298                    shold.sh_handler = SH_SIG_IGN;
     299                }
     300            }
     301            else
     302#endif
     303            {
     304                /* fake */
     305#ifndef _MSC_VER
     306                assert(0);
     307                old.sa_handler = SIG_DFL;
     308                old.sa_flags = 0;
     309                sigemptyset(&shold.sh_mask);
     310                sigaddset(&shold.sh_mask, signo);
     311#endif
     312                shold.sh_flags = 0;
     313                sh_sigemptyset(&shold.sh_mask);
     314                sh_sigaddset(&shold.sh_mask, signo);
     315                shold.sh_handler = SH_SIG_DFL;
     316            }
     317
     318            /* update globals */
     319#ifndef _MSC_VER
     320            g_sig_state[signo].sa = old;
     321#else
     322            g_sig_state[signo].sa.sa_handle = SIG_DFL;
     323            g_sig_state[signo].sa.sa_flags = 0;
     324            g_sig_state[signo].sa.sa_mask = shold.sh_mask;
     325#endif
     326
     327            /* update all shells */
     328            for (cur = g_sh_head; cur; cur = cur->next)
     329            {
     330                assert(cur->sigactions[signo].sh_handler == SH_SIG_UNK);
     331                cur->sigactions[signo] = shold;
     332            }
     333        }
     334
     335        shmtx_leave(&g_sh_mtx, &tmp);
     336    }
     337}
     338
     339
     340/**
     341 * Handler for external signals.
     342 *
     343 * @param   signo       The signal.
     344 */
     345static void sh_sig_common_handler(int signo)
     346{
     347
     348}
     349
     350
    131351int sh_sigaction(shinstance *psh, int signo, const struct shsigaction *newp, struct shsigaction *oldp)
    132352{
    133 #ifdef SH_PURE_STUB_MODE
    134     return -1;
    135 #elif defined(SH_STUB_MODE)
    136 # ifdef _MSC_VER
    137     return -1;
    138 # else
    139     struct sigaction old;
    140     if (newp)
     353    printf("sh_sigaction: signo=%d newp=%p oldp=%p\n", signo, newp, oldp);
     354
     355    /*
     356     * Input validation.
     357     */
     358    if (signo >= NSIG || signo <= 0)
     359    {
     360        errno = EINVAL;
    141361        return -1;
    142     if (sigaction(signo, NULL, &old))
     362    }
     363
     364#ifdef SH_PURE_STUB_MODE
     365    return -1;
     366#else
     367
     368    /*
     369     * Make sure our data is correct.
     370     */
     371    sh_int_lazy_init_sigaction(psh, signo);
     372
     373    /*
     374     * Get the old one if requested.
     375     */
     376    if (oldp)
     377        *oldp = psh->sigactions[signo];
     378
     379    /*
     380     * Set the new one if it has changed.
     381     *
     382     * This will be attempted coordinated with the other signal handlers so
     383     * that we can arrive at a common denominator.
     384     */
     385    if (    newp
     386        &&  memcmp(&psh->sigactions[signo], newp, sizeof(*newp)))
     387    {
     388        shmtxtmp tmp;
     389        shmtx_enter(&g_sh_mtx, &tmp);
     390
     391        /* Undo the accounting for the current entry. */
     392        if (psh->sigactions[signo].sh_handler == SH_SIG_IGN)
     393            g_sig_state[signo].num_ignore--;
     394        else if (psh->sigactions[signo].sh_handler != SH_SIG_DFL)
     395            g_sig_state[signo].num_specific--;
     396        if (psh->sigactions[signo].sh_flags & SA_RESTART)
     397            g_sig_state[signo].num_restart--;
     398
     399        /* Set the new entry. */
     400        psh->sigactions[signo] = *newp;
     401
     402        /* Add the bits for the new action entry. */
     403        if (psh->sigactions[signo].sh_handler == SH_SIG_IGN)
     404            g_sig_state[signo].num_ignore++;
     405        else if (psh->sigactions[signo].sh_handler != SH_SIG_DFL)
     406            g_sig_state[signo].num_specific++;
     407        if (psh->sigactions[signo].sh_flags & SA_RESTART)
     408            g_sig_state[signo].num_restart++;
     409
     410        /*
     411         * Calc new common action.
     412         *
     413         * This is quit a bit ASSUMPTIVE about the limited use. We will not
     414         * bother synching the mask, and we pretend to care about SA_RESTART.
     415         * The only thing we really actually care about is the sh_handler.
     416         *
     417         * On second though, it's possible we should just tie this to the root
     418         * shell since it only really applies to external signal ...
     419         */
     420        if (    g_sig_state[signo].num_specific
     421            ||  g_sig_state[signo].num_ignore != g_num_shells)
     422            g_sig_state[signo].sa.sa_handler = sh_sig_common_handler;
     423        else if (g_sig_state[signo].num_ignore)
     424            g_sig_state[signo].sa.sa_handler = SIG_DFL;
     425        else
     426            g_sig_state[signo].sa.sa_handler = SIG_DFL;
     427        g_sig_state[signo].sa.sa_flags = psh->sigactions[signo].sh_flags & SA_RESTART;
     428
     429# ifdef _MSC_VER
     430        if (signal(signo, g_sig_state[signo].sa.sa_handler) == SIG_ERR)
     431# else
     432        if (sigaction(signo, &g_sig_state[signo].sa, NULL))
     433# endif
     434            assert(0);
     435
     436        shmtx_leave(&g_sh_mtx, &tmp);
     437    }
     438
     439    return 0;
     440#endif
     441}
     442
     443shsig_t sh_signal(shinstance *psh, int signo, shsig_t handler)
     444{
     445    shsigaction_t sa;
     446    shsig_t ret;
     447
     448    /*
     449     * Implementation using sh_sigaction.
     450     */
     451    if (sh_sigaction(psh, signo, NULL, &sa))
     452        return SH_SIG_ERR;
     453
     454    ret = sa.sh_handler;
     455    sa.sh_flags &= SA_RESTART;
     456    sa.sh_handler = handler;
     457    sh_sigemptyset(&sa.sh_mask);
     458    sh_sigaddset(&sa.sh_mask, signo); /* ?? */
     459    if (sh_sigaction(psh, signo, &sa, NULL))
     460        return SH_SIG_ERR;
     461
     462    return ret;
     463}
     464
     465int sh_siginterrupt(shinstance *psh, int signo, int interrupt)
     466{
     467    shsigaction_t sa;
     468    int oldflags = 0;
     469
     470    /*
     471     * Implementation using sh_sigaction.
     472     */
     473    if (sh_sigaction(psh, signo, NULL, &sa))
    143474        return -1;
    144     oldp->sh_flags = old.sa_flags;
    145     oldp->sh_handler = old.sa_handler;
    146     oldp->sh_mask = old.sa_mask;
    147     return 0;
    148 # endif
    149 #else
    150 #endif
    151 }
    152 
    153 shsig_t sh_signal(shinstance *psh, int signo, shsig_t handler)
    154 {
    155     return (shsig_t)-1;
    156 }
    157 
    158 int sh_siginterrupt(shinstance *psh, int signo, int interrupt)
    159 {
    160     return -1;
     475    oldflags = sa.sh_flags;
     476    if (interrupt)
     477        sa.sh_flags &= ~SA_RESTART;
     478    else
     479        sa.sh_flags |= ~SA_RESTART;
     480    if (!((oldflags ^ sa.sh_flags) & SA_RESTART))
     481        return 0; /* unchanged. */
     482
     483    return sh_sigaction(psh, signo, &sa, NULL);
    161484}
    162485
     
    166489}
    167490
     491void sh_sigaddset(shsigset_t *setp, int signo)
     492{
     493#ifdef _MSC_VER
     494    *setp |= 1U << signo;
     495#else
     496    sigaddset(setp, signo);
     497#endif
     498}
     499
     500void sh_sigdelset(shsigset_t *setp, int signo)
     501{
     502#ifdef _MSC_VER
     503    *setp &= ~(1U << signo);
     504#else
     505    sigdelset(setp, signo);
     506#endif
     507}
     508
     509int sh_sigismember(shsigset_t *setp, int signo)
     510{
     511#ifdef _MSC_VER
     512    return !!(*setp & (1U << signo));
     513#else
     514    return !!sigismember(setp, signo);
     515#endif
     516}
     517
    168518int sh_sigprocmask(shinstance *psh, int operation, shsigset_t const *newp, shsigset_t *oldp)
    169519{
    170     return -1;
     520#ifdef SH_PURE_STUB_MODE
     521    return -1;
     522#elif defined(SH_STUB_MODE)
     523    (void)psh;
     524# ifdef _MSC_VER
     525    return -1;
     526# else
     527    return sigprocmask(operation, newp, oldp);
     528# endif
     529#else
     530#endif
    171531}
    172532
     
    175535#ifdef SH_PURE_STUB_MODE
    176536#elif defined(SH_STUB_MODE)
     537    (void)psh;
    177538    abort();
    178539#else
     
    184545#ifdef SH_PURE_STUB_MODE
    185546#elif defined(SH_STUB_MODE)
     547    (void)psh;
    186548    raise(SIGINT);
    187549#else
     
    194556    return -1;
    195557#elif defined(SH_STUB_MODE)
     558    (void)psh;
    196559# ifdef _MSC_VER
    197560    return -1;
     
    209572    return -1;
    210573#elif defined(SH_STUB_MODE)
     574    (void)psh;
    211575# ifdef _MSC_VER
    212576    return -1;
     
    224588    return 0;
    225589#elif defined(SH_STUB_MODE)
     590    (void)psh;
    226591# ifdef _MSC_VER
    227592    return 0;
     
    251616    return -1;
    252617#elif defined(SH_STUB_MODE)
     618    (void)psh;
    253619# ifdef _MSC_VER
    254620    return -1;
     
    266632    return -1;
    267633#elif defined(SH_STUB_MODE)
     634    (void)psh;
    268635# ifdef _MSC_VER
    269636    return -1;
     
    282649    return -1;
    283650#elif defined(SH_STUB_MODE)
     651    (void)psh;
    284652    _exit(rc);
    285653#else
     
    292660    return -1;
    293661#elif defined(SH_STUB_MODE)
     662    (void)psh;
    294663# ifdef _MSC_VER
    295664    return -1;
     
    306675    return 0;
    307676#elif defined(SH_STUB_MODE)
     677    (void)psh;
    308678# ifdef _MSC_VER
    309679    return 0;
     
    320690    return 0;
    321691#elif defined(SH_STUB_MODE)
     692    (void)psh;
    322693# ifdef _MSC_VER
    323694    return 0;
     
    334705    return 0;
    335706#elif defined(SH_STUB_MODE)
     707    (void)psh;
    336708# ifdef _MSC_VER
    337709    return 0;
     
    348720    return 0;
    349721#elif defined(SH_STUB_MODE)
     722    (void)psh;
    350723# ifdef _MSC_VER
    351724    return 0;
     
    362735    return 0;
    363736#elif defined(SH_STUB_MODE)
     737    (void)psh;
    364738# ifdef _MSC_VER
    365739    return _getpid();
     
    376750    return 0;
    377751#elif defined(SH_STUB_MODE)
     752    (void)psh;
    378753# ifdef _MSC_VER
    379754    return _getpid();
     
    390765    return pid;
    391766#elif defined(SH_STUB_MODE)
     767    (void)psh;
    392768# ifdef _MSC_VER
    393769    return pid;
     
    404780    return -1;
    405781#elif defined(SH_STUB_MODE)
     782    (void)psh;
    406783# ifdef _MSC_VER
    407784    return -1;
     
    421798    return -1;
    422799#elif defined(SH_STUB_MODE)
     800    (void)psh;
    423801# ifdef _MSC_VER
    424802    return -1;
     
    435813    return -1;
    436814#elif defined(SH_STUB_MODE)
     815    (void)psh;
    437816# ifdef _MSC_VER
    438817    return -1;
     
    449828    return -1;
    450829#elif defined(SH_STUB_MODE)
     830    (void)psh;
    451831# ifdef _MSC_VER
    452832    return -1;
     
    463843    return -1;
    464844#elif defined(SH_STUB_MODE)
     845    (void)psh;
    465846# ifdef _MSC_VER
    466847    return -1;
Note: See TracChangeset for help on using the changeset viewer.