void simplifyPFBlock(const Edges& toUnlink, const PFBlock& block, Blocks& simplifiedBlocks, Nodes& history) { // take a block, unlink some of the edges and // create smaller blocks or a simplified blocks // or if nothing has changed take a copy of the original block if (toUnlink.size() == 0) { // no change needed, just make a copy of block PFBlock newblock(block.elementIds(), block.edges(), simplifiedBlocks.size(), 's'); // will copy edges and ids PDebug::write("Made {}", newblock); auto id = newblock.id(); simplifiedBlocks.emplace(id, std::move(newblock)); // update history makeHistoryLinks(block.elementIds(), {id}, history); } else { Edges modifiedEdges; for (auto edge : block.edges()) { // copying edges Edge e = edge.second; if (toUnlink.find(edge.first) != toUnlink.end()) { e.setLinked(false); } modifiedEdges.emplace(e.key(), e); } // create new blocks and add into simplifiedBlocks buildPFBlocks(block.elementIds(), modifiedEdges, 's', simplifiedBlocks, history); } }
static PyObject * deque_extendleft(dequeobject *deque, PyObject *iterable) { PyObject *it, *item; it = PyObject_GetIter(iterable); if (it == NULL) return NULL; while ((item = PyIter_Next(it)) != NULL) { deque->state++; if (deque->leftindex == 0) { block *b = newblock(NULL, deque->leftblock, deque->len); if (b == NULL) { Py_DECREF(item); Py_DECREF(it); return NULL; } assert(deque->leftblock->leftlink == NULL); deque->leftblock->leftlink = b; deque->leftblock = b; deque->leftindex = BLOCKLEN; } deque->len++; deque->leftindex--; deque->leftblock->data[deque->leftindex] = item; TRIM(deque, deque_pop); } Py_DECREF(it); if (PyErr_Occurred()) return NULL; Py_RETURN_NONE; }
void storage_test() { Block* data=new Block(); Address address; address.database_name="zyh"; address.file_name="friend"; address.file_offset=8; Storage storage; try{ storage.read_data(address,data); for (int i=0;i<8;i++) { std::cout << (*data)[i]; } } catch( Error error) { error.print_error(); } unsigned char newdata[BLOCK_SIZE]; for (int i=0;i<BLOCK_SIZE;i++) { newdata[i]='s'; } Block newblock(newdata); try{ storage.write_data(address,&newblock); } catch( Error error) { error.print_error(); } }
static PyObject * deque_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { dequeobject *deque; block *b; /* create dequeobject structure */ deque = (dequeobject *)type->tp_alloc(type, 0); if (deque == NULL) return NULL; b = newblock(NULL, NULL, 0); if (b == NULL) { Py_DECREF(deque); return NULL; } assert(BLOCKLEN >= 2); deque->leftblock = b; deque->rightblock = b; deque->leftindex = CENTER + 1; deque->rightindex = CENTER; deque->len = 0; deque->state = 0; deque->weakreflist = NULL; deque->maxlen = -1; return (PyObject *)deque; }
inline void check_curblock(size_t toread) { if (curblock == NULL || curblock->end < edataoffset+toread) { if (curblock != NULL) { if (!curblock->active) { curblock->release(iomgr); } } // Load next std::string blockfilename = filename_shard_edata_block(filename_edata, (int) (edataoffset / blocksize), blocksize); int edata_session = iomgr->open_session(blockfilename, false, true); sblock<ET> newblock(edata_session, edata_session, true, blockfilename); // We align blocks always to the blocksize, even if that requires // allocating and reading some unnecessary data. newblock.offset = (edataoffset / blocksize) * blocksize; // Align size_t correction = edataoffset - newblock.offset; newblock.end = std::min(edatafilesize, newblock.offset + blocksize); assert(newblock.end >= newblock.offset); int realsize = get_block_uncompressed_size(blockfilename, newblock.end - newblock.offset); iomgr->managed_malloc(edata_session, &newblock.data, realsize, newblock.offset); newblock.ptr = newblock.data + correction; activeblocks.push_back(newblock); curblock = &activeblocks[activeblocks.size()-1]; curblock->active = true; curblock->read_now(iomgr); } }
/*! \brief Returns a pointer to a struct within our BlockHeap that's free for * the taking. * \param bh Pointer to the Blockheap * \return Address pointer to allocated data space, or NULL if unsuccessful */ void * BlockHeapAlloc(BlockHeap *bh) { Block *walker = NULL; dlink_node *new_node = NULL; assert(bh != NULL); if (bh->freeElems == 0) { /* Allocate new block and assign */ /* newblock returns 1 if unsuccessful, 0 if not */ if (newblock(bh)) { /* That didn't work..try to garbage collect */ BlockHeapGarbageCollect(bh); if (newblock(bh)) outofmemory(); /* Well that didn't work either...bail */ } } for (walker = bh->base; walker != NULL; walker = walker->next) { if (walker->freeElems > 0) { --bh->freeElems; --walker->freeElems; new_node = walker->free_list.head; dlinkDelete(new_node, &walker->free_list); assert(new_node->data != NULL); memset(new_node->data, 0, bh->elemSize); return new_node->data; } } assert(0 == 1); outofmemory(); return NULL; }
/* copy blocks and create definitions for the primed values as needed */ static void makenext(void) { SemBlock *b, *c; BitSet *copy; int i, j, ch; copy = bsnew(nblocks); for(i = 0; i < nblocks; i++) { b = blocks[i]; if(descendsum(b->phi, countnext) + descendsum(b->cont, countnext) > 0) bsadd(copy, i); } do { ch = 0; for(i = -1; i = bsiter(copy, i), i >= 0; ) { b = blocks[i]; for(j = 0; j < b->nto; j++) ch += bsadd(copy, b->to[j]->idx) == 0; for(j = 0; j < b->nfrom; j++) ch += bsadd(copy, b->from[j]->idx) == 0; } } while(ch != 0); dupl = emalloc(nblocks * sizeof(SemBlock *)); for(i = -1; i = bsiter(copy, i), i >= 0; ) dupl[i] = newblock(); for(i = -1; i = bsiter(copy, i), i >= 0; ) { b = blocks[i]; c = dupl[i]; c->nto = b->nto; c->to = emalloc(sizeof(SemBlock *) * c->nto); c->nfrom = b->nfrom; c->from = emalloc(sizeof(SemBlock *) * c->nfrom); for(j = 0; j < b->nto; j++) { c->to[j] = dupl[b->to[j]->idx]; assert(c->to[j] != nil); } for(j = 0; j < b->nfrom; j++) { c->from[j] = dupl[b->from[j]->idx]; assert(c->from[j] != nil); } c->phi = mkblock(descend(b->phi, nil, makenext1)); c->cont = mkblock(descend(b->cont, nil, makenext1)); c->jump = mkblock(descend(b->jump, nil, makenext1)); } for(i = 0; i < nblocks; i++) { b = blocks[i]; b->phi = mkblock(descend(b->phi, nil, deldefs)); b->cont = mkblock(descend(b->cont, nil, deldefs)); } bsfree(copy); }
/* add initialization statements to blocks as needed */ static void sinitbuild(SemBlock *b) { SemBlock *yes, *no, *then; SemInit *si; ASTNode *p; SemVar *nv, *v; SemTrigger *t; for(t = sinits; t != nil; t = t->next) { yes = newblock(); no = newblock(); then = newblock(); yes->cont = node(ASTBLOCK, nil); then->phi = node(ASTBLOCK, nil); b->jump = node(ASTIF, t->trigger, node(ASTSEMGOTO, yes), node(ASTSEMGOTO, no)); yes->jump = node(ASTSEMGOTO, then); no->jump = node(ASTSEMGOTO, then); mkftlist(b, 1, yes, no, nil); mkftlist(yes, 0, b, nil); mkftlist(yes, 1, then, nil); mkftlist(no, 0, b, nil); mkftlist(no, 1, then, nil); mkftlist(then, 0, yes, no, nil); for(si = t->first; si != nil; si = si->tnext) { v = mkvar(si->var->sym, 1); if(--si->var->nsinits > 0) nv = mkvar(si->var->sym, 1); else nv = si->var->sym->semc[1]; yes->cont->nl = nlcat(yes->cont->nl, nl(node(ASTASS, OPNOP, node(ASTSSA, v), si->val))); p = node(ASTPHI); p->nl = nls(node(ASTSSA, v), node(ASTSSA, ssaget(sinitvars, v->sym, 1)), nil); then->phi->nl = nlcat(then->phi->nl, nl(node(ASTASS, OPNOP, node(ASTSSA, nv), p))); defsadd(sinitvars, nv, 1); } b = then; } }
/* ************************************************************************ */ BlockHeap * BlockHeapCreate(size_t elemsize, int elemsperblock) { BlockHeap *bh; assert(elemsize > 0 && elemsperblock > 0); /* Catch idiotic requests up front */ if ((elemsize <= 0) || (elemsperblock <= 0)) { outofmemory(); /* die.. out of memory */ } /* Allocate our new BlockHeap */ bh = (BlockHeap *) calloc(1, sizeof(BlockHeap)); if (bh == NULL) { outofmemory(); /* die.. out of memory */ } #ifdef MEMDEBUG elemsize += sizeof(MemoryEntry); #endif if((elemsize % sizeof(void *)) != 0) { /* Pad to even pointer boundary */ elemsize += sizeof(void *); elemsize &= ~(sizeof(void *) - 1); } bh->elemSize = elemsize; bh->elemsPerBlock = elemsperblock; bh->blocksAllocated = 0; bh->freeElems = 0; bh->base = NULL; /* Be sure our malloc was successful */ if (newblock(bh)) { if(bh != NULL) free(bh); outofmemory(); /* die.. out of memory */ } if (bh == NULL) { outofmemory(); /* die.. out of memory */ } return(bh); }
void alias0(const char *s, const char *old) { entree *ep, *e; GEN x; ep = fetch_entry(old); e = fetch_entry(s); if (EpVALENCE(e) != EpALIAS && EpVALENCE(e) != EpNEW) pari_err(e_MISC,"can't replace an existing symbol by an alias"); freeep(e); x = newblock(2); x[0] = evaltyp(t_STR)|_evallg(2); /* for getheap */ gel(x,1) = (GEN)ep; e->value=x; e->valence=EpALIAS; }
static PyObject * deque_extendleft(dequeobject *deque, PyObject *iterable) { PyObject *it, *item; /* Handle case where id(deque) == id(iterable) */ if ((PyObject *)deque == iterable) { PyObject *result; PyObject *s = PySequence_List(iterable); if (s == NULL) return NULL; result = deque_extendleft(deque, s); Py_DECREF(s); return result; } it = PyObject_GetIter(iterable); if (it == NULL) return NULL; if (deque->maxlen == 0) return consume_iterator(it); while ((item = PyIter_Next(it)) != NULL) { deque->state++; if (deque->leftindex == 0) { block *b = newblock(NULL, deque->leftblock, deque->len); if (b == NULL) { Py_DECREF(item); Py_DECREF(it); return NULL; } assert(deque->leftblock->leftlink == NULL); deque->leftblock->leftlink = b; deque->leftblock = b; deque->leftindex = BLOCKLEN; } deque->len++; deque->leftindex--; deque->leftblock->data[deque->leftindex] = item; TRIM(deque, deque_pop); } Py_DECREF(it); if (PyErr_Occurred()) return NULL; Py_RETURN_NONE; }
void * _BlockHeapAlloc(BlockHeap * bh) { Block *walker; dlink_node *new_node; assert(bh != NULL); if (bh == NULL) { return(NULL); } if (bh->freeElems == 0) { /* Allocate new block and assign */ /* newblock returns 1 if unsuccessful, 0 if not */ if (newblock(bh)) { /* That didn't work..try to garbage collect */ BlockHeapGarbageCollect(bh); if(bh->freeElems == 0) { outofmemory(); /* Well that didn't work either...bail */ } } } for (walker = bh->base; walker != NULL; walker = walker->next) { if (walker->freeElems > 0) { bh->freeElems--; walker->freeElems--; new_node = walker->free_list.head; dlinkDelete(new_node, &walker->free_list); dlinkAdd(new_node->data, new_node, &walker->used_list); assert(new_node->data != NULL); if(new_node->data == NULL) outofmemory(); return (new_node->data); } } assert(0 == 1); return(NULL); /* If you get here, something bad happened ! */ }
/* ************************************************************************ */ BlockHeap * BlockHeapCreate (size_t elemsize, int elemsperblock) { BlockHeap *bh; /* Catch idiotic requests up front */ if ((elemsize <= 0) || (elemsperblock <= 0)) { outofmemory(); /* die.. out of memory */ } /* Allocate our new BlockHeap */ bh = (BlockHeap *) MyMalloc( sizeof (BlockHeap)); if (bh == NULL) { outofmemory(); /* die.. out of memory */ } elemsize = elemsize + (elemsize & (sizeof(void *) - 1)); bh->elemSize = elemsize; bh->elemsPerBlock = elemsperblock; bh->blocksAllocated = 0; bh->freeElems = 0; bh->numlongs = (bh->elemsPerBlock / (sizeof(long) * 8)) + 1; if ( (bh->elemsPerBlock % (sizeof(long) * 8)) == 0) bh->numlongs--; bh->base = NULL; /* Be sure our malloc was successful */ if (newblock(bh)) { free(bh); outofmemory(); /* die.. out of memory */ } /* DEBUG */ if(bh == NULL) { outofmemory(); /* die.. out of memory */ } return bh; }
static PyObject * deque_appendleft(dequeobject *deque, PyObject *item) { deque->state++; if (deque->leftindex == 0) { block *b = newblock(NULL, deque->leftblock, deque->len); if (b == NULL) return NULL; assert(deque->leftblock->leftlink == NULL); deque->leftblock->leftlink = b; deque->leftblock = b; deque->leftindex = BLOCKLEN; } Py_INCREF(item); deque->len++; deque->leftindex--; deque->leftblock->data[deque->leftindex] = item; TRIM(deque, deque_pop); Py_RETURN_NONE; }
static PyObject * deque_append(dequeobject *deque, PyObject *item) { deque->state++; if (deque->rightindex == BLOCKLEN-1) { block *b = newblock(deque->rightblock, NULL, deque->len); if (b == NULL) return NULL; assert(deque->rightblock->rightlink == NULL); deque->rightblock->rightlink = b; deque->rightblock = b; deque->rightindex = -1; } Py_INCREF(item); deque->len++; deque->rightindex++; deque->rightblock->data[deque->rightindex] = item; TRIM(deque, deque_popleft); Py_RETURN_NONE; }
/*! \brief Creates a new blockheap * * Creates a new blockheap from which smaller blocks can be allocated. * Intended to be used instead of multiple calls to malloc() when * performance is an issue. * * \param name Name of the blockheap * \param elemsize Size of the basic element to be stored * \param elemsperblock Number of elements to be stored in a single block of * memory. When the blockheap runs out of free memory, * it will allocate elemsize * elemsperblock more. * \return Pointer to new BlockHeap, or NULL if unsuccessful */ BlockHeap * BlockHeapCreate(const char *const name, size_t elemsize, int elemsperblock) { BlockHeap *bh = NULL; assert(elemsize > 0 && elemsperblock > 0); /* Catch idiotic requests up front */ if ((elemsize <= 0) || (elemsperblock <= 0)) outofmemory(); /* die.. out of memory */ /* Allocate our new BlockHeap */ if ((bh = calloc(1, sizeof(BlockHeap))) == NULL) outofmemory(); /* die.. out of memory */ if ((elemsize % sizeof(void *)) != 0) { /* Pad to even pointer boundary */ elemsize += sizeof(void *); elemsize &= ~(sizeof(void *) - 1); } bh->name = name; bh->elemSize = elemsize; bh->elemsPerBlock = elemsperblock; /* Be sure our malloc was successful */ if (newblock(bh)) { if (bh != NULL) free(bh); outofmemory(); /* die.. out of memory */ } bh->next = heap_list; heap_list = bh; return bh; }
static int comexec(struct op *t, struct tbl * volatile tp, const char **ap, volatile int flags, volatile int *xerrok) { int i; volatile int rv = 0; const char *cp; const char **lastp; /* Must be static (XXX but why?) */ static struct op texec; int type_flags; bool resetspec; int fcflags = FC_BI|FC_FUNC|FC_PATH; struct block *l_expand, *l_assign; int optc; const char *exec_argv0 = NULL; bool exec_clrenv = false; /* snag the last argument for $_ */ if (Flag(FTALKING) && *(lastp = ap)) { /* * XXX not the same as AT&T ksh, which only seems to set $_ * after a newline (but not in functions/dot scripts, but in * interactive and script) - perhaps save last arg here and * set it in shell()?. */ while (*++lastp) ; /* setstr() can't fail here */ setstr(typeset("_", LOCAL, 0, INTEGER, 0), *--lastp, KSH_RETURN_ERROR); } /** * Deal with the shell builtins builtin, exec and command since * they can be followed by other commands. This must be done before * we know if we should create a local block which must be done * before we can do a path search (in case the assignments change * PATH). * Odd cases: * FOO=bar exec >/dev/null FOO is kept but not exported * FOO=bar exec foobar FOO is exported * FOO=bar command exec >/dev/null FOO is neither kept nor exported * FOO=bar command FOO is neither kept nor exported * PATH=... foobar use new PATH in foobar search */ resetspec = false; while (tp && tp->type == CSHELL) { /* undo effects of command */ fcflags = FC_BI|FC_FUNC|FC_PATH; if (tp->val.f == c_builtin) { if ((cp = *++ap) == NULL || (!strcmp(cp, "--") && (cp = *++ap) == NULL)) { tp = NULL; break; } if ((tp = findcom(cp, FC_BI)) == NULL) errorf("%s: %s: %s", Tbuiltin, cp, "not a builtin"); if (tp->type == CSHELL && (tp->val.f == c_cat #ifdef MKSH_PRINTF_BUILTIN || tp->val.f == c_printf #endif )) break; continue; } else if (tp->val.f == c_exec) { if (ap[1] == NULL) break; ksh_getopt_reset(&builtin_opt, GF_ERROR); while ((optc = ksh_getopt(ap, &builtin_opt, "a:c")) != -1) switch (optc) { case 'a': exec_argv0 = builtin_opt.optarg; break; case 'c': exec_clrenv = true; /* ensure we can actually do this */ resetspec = true; break; default: rv = 2; goto Leave; } ap += builtin_opt.optind; flags |= XEXEC; } else if (tp->val.f == c_command) { bool saw_p = false; /* * Ugly dealing with options in two places (here * and in c_command(), but such is life) */ ksh_getopt_reset(&builtin_opt, 0); while ((optc = ksh_getopt(ap, &builtin_opt, ":p")) == 'p') saw_p = true; if (optc != -1) /* command -vV or something */ break; /* don't look for functions */ fcflags = FC_BI|FC_PATH; if (saw_p) { if (Flag(FRESTRICTED)) { warningf(true, "%s: %s", "command -p", "restricted"); rv = 1; goto Leave; } fcflags |= FC_DEFPATH; } ap += builtin_opt.optind; /* * POSIX says special builtins lose their status * if accessed using command. */ resetspec = true; if (!ap[0]) { /* ensure command with no args exits with 0 */ subst_exstat = 0; break; } } else if (tp->val.f == c_cat) { /* if we have any flags, do not use the builtin */ if (ap[1] && ap[1][0] == '-' && ap[1][1] != '\0' && /* argument, begins with -, is not - or -- */ (ap[1][1] != '-' || ap[1][2] != '\0')) { struct tbl *ext_cat; ext_cat = findcom(Tcat, FC_PATH | FC_FUNC); if (ext_cat && (ext_cat->type != CTALIAS || (ext_cat->flag & ISSET))) tp = ext_cat; } break; #ifdef MKSH_PRINTF_BUILTIN } else if (tp->val.f == c_printf) { struct tbl *ext_printf; ext_printf = findcom(Tprintf, FC_PATH | FC_FUNC); if (ext_printf && (ext_printf->type != CTALIAS || (ext_printf->flag & ISSET))) tp = ext_printf; break; #endif } else if (tp->val.f == c_trap) { t->u.evalflags &= ~DOTCOMEXEC; break; } else break; tp = findcom(ap[0], fcflags & (FC_BI|FC_FUNC)); } if (t->u.evalflags & DOTCOMEXEC) flags |= XEXEC; l_expand = e->loc; if (!resetspec && (!ap[0] || (tp && (tp->flag & KEEPASN)))) type_flags = 0; else { /* create new variable/function block */ newblock(); /* ksh functions don't keep assignments, POSIX functions do. */ if (!resetspec && tp && tp->type == CFUNC && !(tp->flag & FKSH)) type_flags = EXPORT; else type_flags = LOCAL|LOCAL_COPY|EXPORT; } l_assign = e->loc; if (exec_clrenv) l_assign->flags |= BF_STOPENV; if (Flag(FEXPORT)) type_flags |= EXPORT; if (Flag(FXTRACE)) change_xtrace(2, false); for (i = 0; t->vars[i]; i++) { /* do NOT lookup in the new var/fn block just created */ e->loc = l_expand; cp = evalstr(t->vars[i], DOASNTILDE | DOSCALAR); e->loc = l_assign; if (Flag(FXTRACE)) { const char *ccp; ccp = skip_varname(cp, true); if (*ccp == '+') ++ccp; if (*ccp == '=') ++ccp; shf_write(cp, ccp - cp, shl_xtrace); print_value_quoted(shl_xtrace, ccp); shf_putc(' ', shl_xtrace); } /* but assign in there as usual */ typeset(cp, type_flags, 0, 0, 0); } if (Flag(FXTRACE)) { change_xtrace(2, false); if (ap[rv = 0]) { xtrace_ap_loop: print_value_quoted(shl_xtrace, ap[rv]); if (ap[++rv]) { shf_putc(' ', shl_xtrace); goto xtrace_ap_loop; } } change_xtrace(1, false); } if ((cp = *ap) == NULL) { rv = subst_exstat; goto Leave; } else if (!tp) { if (Flag(FRESTRICTED) && vstrchr(cp, '/')) { warningf(true, "%s: %s", cp, "restricted"); rv = 1; goto Leave; } tp = findcom(cp, fcflags); } switch (tp->type) { /* shell built-in */ case CSHELL: do_call_builtin: rv = call_builtin(tp, (const char **)ap, null, resetspec); if (resetspec && tp->val.f == c_shift) { l_expand->argc = l_assign->argc; l_expand->argv = l_assign->argv; } break; /* function call */ case CFUNC: { volatile uint32_t old_inuse; const char * volatile old_kshname; volatile uint8_t old_flags[FNFLAGS]; if (!(tp->flag & ISSET)) { struct tbl *ftp; if (!tp->u.fpath) { rv = (tp->u2.errnov == ENOENT) ? 127 : 126; warningf(true, "%s: %s %s: %s", cp, "can't find", "function definition file", cstrerror(tp->u2.errnov)); break; } if (include(tp->u.fpath, 0, NULL, false) < 0) { if (!strcmp(cp, Tcat)) { no_cat_in_FPATH: tp = findcom(Tcat, FC_BI); goto do_call_builtin; } #ifdef MKSH_PRINTF_BUILTIN if (!strcmp(cp, Tprintf)) { no_printf_in_FPATH: tp = findcom(Tprintf, FC_BI); goto do_call_builtin; } #endif warningf(true, "%s: %s %s %s: %s", cp, "can't open", "function definition file", tp->u.fpath, cstrerror(errno)); rv = 127; break; } if (!(ftp = findfunc(cp, hash(cp), false)) || !(ftp->flag & ISSET)) { if (!strcmp(cp, Tcat)) goto no_cat_in_FPATH; #ifdef MKSH_PRINTF_BUILTIN if (!strcmp(cp, Tprintf)) goto no_printf_in_FPATH; #endif warningf(true, "%s: %s %s", cp, "function not defined by", tp->u.fpath); rv = 127; break; } tp = ftp; } /* * ksh functions set $0 to function name, POSIX * functions leave $0 unchanged. */ old_kshname = kshname; if (tp->flag & FKSH) kshname = ap[0]; else ap[0] = kshname; e->loc->argv = ap; for (i = 0; *ap++ != NULL; i++) ; e->loc->argc = i - 1; /* * ksh-style functions handle getopts sanely, * Bourne/POSIX functions are insane... */ if (tp->flag & FKSH) { e->loc->flags |= BF_DOGETOPTS; e->loc->getopts_state = user_opt; getopts_reset(1); } for (type_flags = 0; type_flags < FNFLAGS; ++type_flags) old_flags[type_flags] = shell_flags[type_flags]; change_xtrace((Flag(FXTRACEREC) ? Flag(FXTRACE) : 0) | ((tp->flag & TRACE) ? 1 : 0), false); old_inuse = tp->flag & FINUSE; tp->flag |= FINUSE; e->type = E_FUNC; if (!(i = kshsetjmp(e->jbuf))) { execute(tp->val.t, flags & XERROK, NULL); i = LRETURN; } kshname = old_kshname; change_xtrace(old_flags[(int)FXTRACE], false); #ifndef MKSH_LEGACY_MODE if (tp->flag & FKSH) { /* Korn style functions restore Flags on return */ old_flags[(int)FXTRACE] = Flag(FXTRACE); for (type_flags = 0; type_flags < FNFLAGS; ++type_flags) shell_flags[type_flags] = old_flags[type_flags]; } #endif tp->flag = (tp->flag & ~FINUSE) | old_inuse; /* * Were we deleted while executing? If so, free the * execution tree. */ if ((tp->flag & (FDELETE|FINUSE)) == FDELETE) { if (tp->flag & ALLOC) { tp->flag &= ~ALLOC; tfree(tp->val.t, tp->areap); } tp->flag = 0; } switch (i) { case LRETURN: case LERROR: rv = exstat & 0xFF; break; case LINTR: case LEXIT: case LLEAVE: case LSHELL: quitenv(NULL); unwind(i); /* NOTREACHED */ default: quitenv(NULL); internal_errorf("%s %d", "CFUNC", i); } break; } /* executable command */ case CEXEC: /* tracked alias */ case CTALIAS: if (!(tp->flag&ISSET)) { if (tp->u2.errnov == ENOENT) { rv = 127; warningf(true, "%s: %s", cp, "not found"); } else { rv = 126; warningf(true, "%s: %s: %s", cp, "can't execute", cstrerror(tp->u2.errnov)); } break; } /* set $_ to program's full path */ /* setstr() can't fail here */ setstr(typeset("_", LOCAL | EXPORT, 0, INTEGER, 0), tp->val.s, KSH_RETURN_ERROR); /* to fork, we set up a TEXEC node and call execute */ texec.type = TEXEC; /* for vistree/dumptree */ texec.left = t; texec.str = tp->val.s; texec.args = ap; /* in this case we do not fork, of course */ if (flags & XEXEC) { if (exec_argv0) texec.args[0] = exec_argv0; j_exit(); if (!(flags & XBGND) #ifndef MKSH_UNEMPLOYED || Flag(FMONITOR) #endif ) { setexecsig(&sigtraps[SIGINT], SS_RESTORE_ORIG); setexecsig(&sigtraps[SIGQUIT], SS_RESTORE_ORIG); } } rv = exchild(&texec, flags, xerrok, -1); break; } Leave: if (flags & XEXEC) { exstat = rv & 0xFF; unwind(LLEAVE); } return (rv); }
void * BlockHeapAlloc (BlockHeap * bh) { Block *walker; int unit; unsigned long mask; unsigned long ctr; if (bh == NULL) return ((void *) NULL); if (bh->freeElems == 0) { /* Allocate new block and assign */ /* newblock returns 1 if unsuccessful, 0 if not */ if (newblock (bh)) { return ((void *) NULL); } else { walker = bh->base; walker->allocMap[0] = 0x1L; walker->freeElems--; bh->freeElems--; if (bh->base->elems == NULL) return ((void *) NULL); } return ((bh->base)->elems); /* ...and take the first elem. */ } for (walker = bh->base; walker != NULL; walker = walker->next) { if (walker->freeElems > 0) { mask = 0x1L; ctr = 0; unit = 0; while (unit < bh->numlongs) { if ((mask == 0x1L) && (walker->allocMap[unit] == ~0)) { /* Entire subunit is used, skip to next one. */ unit++; ctr = 0; continue; } /* Check the current element, if free allocate block */ if (!(mask & walker->allocMap[unit])) { walker->allocMap[unit] |= mask; /* Mark block as used */ walker->freeElems--; bh->freeElems--; /* And return the pointer * * Address arithemtic is always ca-ca have to make sure * the the bit pattern for the base address is converted * into the same number of bits in an integer type, that * has at least sizeof(unsigned long) at least == * sizeof(void *) -Dianora */ return ((void *) ((unsigned long) walker->elems + ((unit * sizeof (unsigned long) * 8 + ctr) * (unsigned long) bh->elemSize))); } /* Step up to the next unit */ mask <<= 1; ctr++; if (!mask) { mask = 0x1L; unit++; ctr = 0; } } /* while */ } /* if */ } /* for */ return ((void *) NULL); /* If you get here, something bad happened ! */ }
int main(int argc, char *argv[]) { int i; int argi; Source *s; struct block *l; int restricted, errexit; char **wp; struct env env; pid_t ppid; /* make sure argv[] is sane */ if (!*argv) { static const char *empty_argv[] = { "ksh", (char *) 0 }; argv = (char **) empty_argv; argc = 1; } kshname = *argv; ainit(&aperm); /* initialize permanent Area */ /* set up base environment */ memset(&env, 0, sizeof(env)); env.type = E_NONE; ainit(&env.area); e = &env; newblock(); /* set up global l->vars and l->funs */ /* Do this first so output routines (eg, errorf, shellf) can work */ initio(); initvar(); initctypes(); inittraps(); coproc_init(); /* set up variable and command dictionaries */ ktinit(&taliases, APERM, 0); ktinit(&aliases, APERM, 0); ktinit(&homedirs, APERM, 0); /* define shell keywords */ initkeywords(); /* define built-in commands */ ktinit(&builtins, APERM, 64); /* must be 2^n (currently 40 builtins) */ for (i = 0; shbuiltins[i].name != NULL; i++) builtin(shbuiltins[i].name, shbuiltins[i].func); for (i = 0; kshbuiltins[i].name != NULL; i++) builtin(kshbuiltins[i].name, kshbuiltins[i].func); init_histvec(); def_path = _PATH_DEFPATH; { size_t len = confstr(_CS_PATH, (char *) 0, 0); char *new; if (len > 0) { confstr(_CS_PATH, new = alloc(len + 1, APERM), len + 1); def_path = new; } }
extern bool walk(Node *n, bool parent) { top: sigchk(); if (n == NULL) { if (!parent) exit(0); set(TRUE); return TRUE; } switch (n->type) { case nArgs: case nBackq: case nConcat: case nCount: case nFlat: case nLappend: case nRedir: case nVar: case nVarsub: case nWord: exec(glob(glom(n)), parent); /* simple command */ break; case nBody: walk(n->u[0].p, TRUE); WALK(n->u[1].p, parent); /* WALK doesn't fall through */ case nNowait: { int pid; if ((pid = rc_fork()) == 0) { #if defined(RC_JOB) && defined(SIGTTOU) && defined(SIGTTIN) && defined(SIGTSTP) setsigdefaults(FALSE); rc_signal(SIGTTOU, SIG_IGN); /* Berkeleyized version: put it in a new pgroup. */ rc_signal(SIGTTIN, SIG_IGN); rc_signal(SIGTSTP, SIG_IGN); setpgid(0, getpid()); #else setsigdefaults(TRUE); /* ignore SIGINT, SIGQUIT, SIGTERM */ #endif mvfd(rc_open("/dev/null", rFrom), 0); walk(n->u[0].p, FALSE); exit(getstatus()); } if (interactive) fprint(2, "%d\n", pid); varassign("apid", word(nprint("%d", pid), NULL), FALSE); redirq = NULL; /* kill pre-redir queue */ break; } case nAndalso: { bool oldcond = cond; cond = TRUE; if (walk(n->u[0].p, TRUE)) { cond = oldcond; WALK(n->u[1].p, parent); } else cond = oldcond; break; } case nOrelse: { bool oldcond = cond; cond = TRUE; if (!walk(n->u[0].p, TRUE)) { cond = oldcond; WALK(n->u[1].p, parent); } else cond = oldcond; break; } case nBang: set(!walk(n->u[0].p, TRUE)); break; case nIf: { bool oldcond = cond; Node *true_cmd = n->u[1].p, *false_cmd = NULL; if (true_cmd != NULL && true_cmd->type == nElse) { false_cmd = true_cmd->u[1].p; true_cmd = true_cmd->u[0].p; } cond = TRUE; if (!walk(n->u[0].p, TRUE)) true_cmd = false_cmd; /* run the else clause */ cond = oldcond; WALK(true_cmd, parent); } case nWhile: { Jbwrap j; Edata jbreak; Estack e1, e2; bool testtrue, oldcond = cond; cond = TRUE; if (!walk(n->u[0].p, TRUE)) { /* prevent spurious breaks inside test */ cond = oldcond; break; } if (sigsetjmp(j.j, 1)) break; jbreak.jb = &j; except(eBreak, jbreak, &e1); do { Edata block; block.b = newblock(); cond = oldcond; except(eArena, block, &e2); walk(n->u[1].p, TRUE); testtrue = walk(n->u[0].p, TRUE); unexcept(); /* eArena */ cond = TRUE; } while (testtrue); cond = oldcond; unexcept(); /* eBreak */ break; } case nForin: { List *l, *var = glom(n->u[0].p); Jbwrap j; Estack e1, e2; Edata jbreak; if (sigsetjmp(j.j, 1)) break; jbreak.jb = &j; except(eBreak, jbreak, &e1); for (l = listcpy(glob(glom(n->u[1].p)), nalloc); l != NULL; l = l->n) { Edata block; assign(var, word(l->w, NULL), FALSE); block.b = newblock(); except(eArena, block, &e2); walk(n->u[2].p, TRUE); unexcept(); /* eArena */ } unexcept(); /* eBreak */ break; } case nSubshell: if (dofork(TRUE)) { setsigdefaults(FALSE); walk(n->u[0].p, FALSE); rc_exit(getstatus()); } break; case nAssign: if (n->u[0].p == NULL) rc_error("null variable name"); assign(glom(n->u[0].p), glob(glom(n->u[1].p)), FALSE); set(TRUE); break; case nPipe: dopipe(n); break; case nNewfn: { List *l = glom(n->u[0].p); if (l == NULL) rc_error("null function name"); while (l != NULL) { if (dashex) prettyprint_fn(2, l->w, n->u[1].p); fnassign(l->w, n->u[1].p); l = l->n; } set(TRUE); break; } case nRmfn: { List *l = glom(n->u[0].p); while (l != NULL) { if (dashex) fprint(2, "fn %S\n", l->w); fnrm(l->w); l = l->n; } set(TRUE); break; } case nDup: redirq = NULL; break; /* Null command */ case nMatch: { List *a = glob(glom(n->u[0].p)), *b = glom(n->u[1].p); if (dashex) fprint(2, (a != NULL && a->n != NULL) ? "~ (%L) %L\n" : "~ %L %L\n", a, " ", b, " "); set(lmatch(a, b)); break; } case nSwitch: { List *v = glom(n->u[0].p); while (1) { do { n = n->u[1].p; if (n == NULL) return istrue(); } while (n->u[0].p == NULL || n->u[0].p->type != nCase); if (lmatch(v, glom(n->u[0].p->u[0].p))) { for (n = n->u[1].p; n != NULL && (n->u[0].p == NULL || n->u[0].p->type != nCase); n = n->u[1].p) walk(n->u[0].p, TRUE); break; } } break; } case nPre: { List *v; if (n->u[0].p->type == nRedir || n->u[0].p->type == nDup) { if (redirq == NULL && !dofork(parent)) /* subshell on first preredir */ break; setsigdefaults(FALSE); qredir(n->u[0].p); if (!haspreredir(n->u[1].p)) doredirs(); /* no more preredirs, empty queue */ walk(n->u[1].p, FALSE); rc_exit(getstatus()); /* NOTREACHED */ } else if (n->u[0].p->type == nAssign) { if (isallpre(n->u[1].p)) { walk(n->u[0].p, TRUE); WALK(n->u[1].p, parent); } else { Estack e; Edata var; v = glom(n->u[0].p->u[0].p); assign(v, glob(glom(n->u[0].p->u[1].p)), TRUE); var.name = v->w; except(eVarstack, var, &e); walk(n->u[1].p, parent); varrm(v->w, TRUE); unexcept(); /* eVarstack */ } } else panic("unexpected node in preredir section of walk"); break; } case nBrace: if (n->u[1].p == NULL) { WALK(n->u[0].p, parent); } else if (dofork(parent)) { setsigdefaults(FALSE); walk(n->u[1].p, TRUE); /* Do redirections */ redirq = NULL; /* Reset redirection queue */ walk(n->u[0].p, FALSE); /* Do commands */ rc_exit(getstatus()); /* NOTREACHED */ } break; case nEpilog: qredir(n->u[0].p); if (n->u[1].p != NULL) { WALK(n->u[1].p, parent); /* Do more redirections. */ } else { doredirs(); /* Okay, we hit the bottom. */ } break; case nNmpipe: rc_error("named pipes cannot be executed as commands"); /* NOTREACHED */ default: panic("unknown node in walk"); /* NOTREACHED */ } return istrue(); }
static int main_init(int argc, const char *argv[], Source **sp, struct block **lp) { int argi, i; Source *s = NULL; struct block *l; unsigned char restricted_shell, errexit, utf_flag; char *cp; const char *ccp, **wp; struct tbl *vp; struct stat s_stdin; #if !defined(_PATH_DEFPATH) && defined(_CS_PATH) ssize_t k; #endif #if defined(MKSH_EBCDIC) || defined(MKSH_FAUX_EBCDIC) ebcdic_init(); #endif set_ifs(TC_IFSWS); #ifdef __OS2__ os2_init(&argc, &argv); #endif /* do things like getpgrp() et al. */ chvt_reinit(); /* make sure argv[] is sane, for weird OSes */ if (!*argv) { argv = empty_argv; argc = 1; } kshname = argv[0]; /* initialise permanent Area */ ainit(&aperm); /* max. name length: -2147483648 = 11 (+ NUL) */ vtemp = alloc(offsetof(struct tbl, name[0]) + 12, APERM); /* set up base environment */ env.type = E_NONE; ainit(&env.area); /* set up global l->vars and l->funs */ newblock(); /* Do this first so output routines (eg, errorf, shellf) can work */ initio(); /* determine the basename (without '-' or path) of the executable */ ccp = kshname; goto begin_parsing_kshname; while ((i = ccp[argi++])) { if (mksh_cdirsep(i)) { ccp += argi; begin_parsing_kshname: argi = 0; if (*ccp == '-') ++ccp; } } if (!*ccp) ccp = empty_argv[0]; /* * Turn on nohup by default. (AT&T ksh does not have a nohup * option - it always sends the hup). */ Flag(FNOHUP) = 1; /* * Turn on brace expansion by default. AT&T kshs that have * alternation always have it on. */ Flag(FBRACEEXPAND) = 1; /* * Turn on "set -x" inheritance by default. */ Flag(FXTRACEREC) = 1; /* define built-in commands and see if we were called as one */ ktinit(APERM, &builtins, /* currently up to 54 builtins: 75% of 128 = 2^7 */ 7); for (i = 0; mkshbuiltins[i].name != NULL; i++) if (!strcmp(ccp, builtin(mkshbuiltins[i].name, mkshbuiltins[i].func))) Flag(FAS_BUILTIN) = 1; if (!Flag(FAS_BUILTIN)) { /* check for -T option early */ argi = parse_args(argv, OF_FIRSTTIME, NULL); if (argi < 0) return (1); #if defined(MKSH_BINSHPOSIX) || defined(MKSH_BINSHREDUCED) /* are we called as -sh or /bin/sh or so? */ if (!strcmp(ccp, "sh" MKSH_EXE_EXT)) { /* either also turns off braceexpand */ #ifdef MKSH_BINSHPOSIX /* enable better POSIX conformance */ change_flag(FPOSIX, OF_FIRSTTIME, true); #endif #ifdef MKSH_BINSHREDUCED /* enable kludge/compat mode */ change_flag(FSH, OF_FIRSTTIME, true); #endif } #endif } initvar(); inittraps(); coproc_init(); /* set up variable and command dictionaries */ ktinit(APERM, &taliases, 0); ktinit(APERM, &aliases, 0); #ifndef MKSH_NOPWNAM ktinit(APERM, &homedirs, 0); #endif /* define shell keywords */ initkeywords(); init_histvec(); /* initialise tty size before importing environment */ change_winsz(); #ifdef _PATH_DEFPATH def_path = _PATH_DEFPATH; #else #ifdef _CS_PATH if ((k = confstr(_CS_PATH, NULL, 0)) > 0 && confstr(_CS_PATH, cp = alloc(k + 1, APERM), k + 1) == k + 1) def_path = cp; else #endif /* * this is uniform across all OSes unless it * breaks somewhere hard; don't try to optimise, * e.g. add stuff for Interix or remove /usr * for HURD, because e.g. Debian GNU/HURD is * "keeping a regular /usr"; this is supposed * to be a sane 'basic' default PATH */ def_path = MKSH_UNIXROOT "/bin" MKSH_PATHSEPS MKSH_UNIXROOT "/usr/bin" MKSH_PATHSEPS MKSH_UNIXROOT "/sbin" MKSH_PATHSEPS MKSH_UNIXROOT "/usr/sbin"; #endif /* * Set PATH to def_path (will set the path global variable). * (import of environment below will probably change this setting). */ vp = global(TPATH); /* setstr can't fail here */ setstr(vp, def_path, KSH_RETURN_ERROR); #ifndef MKSH_NO_CMDLINE_EDITING /* * Set edit mode to emacs by default, may be overridden * by the environment or the user. Also, we want tab completion * on in vi by default. */ change_flag(FEMACS, OF_SPECIAL, true); #if !MKSH_S_NOVI Flag(FVITABCOMPLETE) = 1; #endif #endif /* import environment */ init_environ(); /* override default PATH regardless of environment */ #ifdef MKSH_DEFPATH_OVERRIDE vp = global(TPATH); setstr(vp, MKSH_DEFPATH_OVERRIDE, KSH_RETURN_ERROR); #endif /* for security */ typeset(TinitIFS, 0, 0, 0, 0); /* assign default shell variable values */ typeset("PATHSEP=" MKSH_PATHSEPS, 0, 0, 0, 0); substitute(initsubs, 0); /* Figure out the current working directory and set $PWD */ vp = global(TPWD); cp = str_val(vp); /* Try to use existing $PWD if it is valid */ set_current_wd((mksh_abspath(cp) && test_eval(NULL, TO_FILEQ, cp, Tdot, true)) ? cp : NULL); if (current_wd[0]) simplify_path(current_wd); /* Only set pwd if we know where we are or if it had a bogus value */ if (current_wd[0] || *cp) /* setstr can't fail here */ setstr(vp, current_wd, KSH_RETURN_ERROR); for (wp = initcoms; *wp != NULL; wp++) { c_builtin(wp); while (*wp != NULL) wp++; } setint_n(global("OPTIND"), 1, 10); kshuid = getuid(); kshgid = getgid(); kshegid = getegid(); safe_prompt = ksheuid ? "$ " : "# "; vp = global("PS1"); /* Set PS1 if unset or we are root and prompt doesn't contain a # */ if (!(vp->flag & ISSET) || (!ksheuid && !strchr(str_val(vp), '#'))) /* setstr can't fail here */ setstr(vp, safe_prompt, KSH_RETURN_ERROR); setint_n((vp = global("BASHPID")), 0, 10); vp->flag |= INT_U; setint_n((vp = global("PGRP")), (mksh_uari_t)kshpgrp, 10); vp->flag |= INT_U; setint_n((vp = global("PPID")), (mksh_uari_t)kshppid, 10); vp->flag |= INT_U; setint_n((vp = global("USER_ID")), (mksh_uari_t)ksheuid, 10); vp->flag |= INT_U; setint_n((vp = global("KSHUID")), (mksh_uari_t)kshuid, 10); vp->flag |= INT_U; setint_n((vp = global("KSHEGID")), (mksh_uari_t)kshegid, 10); vp->flag |= INT_U; setint_n((vp = global("KSHGID")), (mksh_uari_t)kshgid, 10); vp->flag |= INT_U; setint_n((vp = global("RANDOM")), rndsetup(), 10); vp->flag |= INT_U; setint_n((vp_pipest = global("PIPESTATUS")), 0, 10); /* Set this before parsing arguments */ Flag(FPRIVILEGED) = (kshuid != ksheuid || kshgid != kshegid) ? 2 : 0; /* this to note if monitor is set on command line (see below) */ #ifndef MKSH_UNEMPLOYED Flag(FMONITOR) = 127; #endif /* this to note if utf-8 mode is set on command line (see below) */ UTFMODE = 2; if (!Flag(FAS_BUILTIN)) { argi = parse_args(argv, OF_CMDLINE, NULL); if (argi < 0) return (1); } /* process this later only, default to off (hysterical raisins) */ utf_flag = UTFMODE; UTFMODE = 0; if (Flag(FAS_BUILTIN)) { /* auto-detect from environment variables, always */ utf_flag = 3; } else if (Flag(FCOMMAND)) { s = pushs(SSTRINGCMDLINE, ATEMP); if (!(s->start = s->str = argv[argi++])) errorf(Tf_optfoo, "", "", 'c', Treq_arg); while (*s->str) { if (ctype(*s->str, C_QUOTE)) break; s->str++; } if (!*s->str) s->flags |= SF_MAYEXEC; s->str = s->start; #ifdef MKSH_MIDNIGHTBSD01ASH_COMPAT /* compatibility to MidnightBSD 0.1 /bin/sh (kludge) */ if (Flag(FSH) && argv[argi] && !strcmp(argv[argi], "--")) ++argi; #endif if (argv[argi]) kshname = argv[argi++]; } else if (argi < argc && !Flag(FSTDIN)) { s = pushs(SFILE, ATEMP); #ifdef __OS2__ /* * A bug in OS/2 extproc (like shebang) handling makes * it not pass the full pathname of a script, so we need * to search for it. This changes the behaviour of a * simple "mksh foo", but can't be helped. */ s->file = argv[argi++]; if (search_access(s->file, X_OK) != 0) s->file = search_path(s->file, path, X_OK, NULL); if (!s->file || !*s->file) s->file = argv[argi - 1]; #else s->file = argv[argi++]; #endif s->u.shf = shf_open(s->file, O_RDONLY, 0, SHF_MAPHI | SHF_CLEXEC); if (s->u.shf == NULL) { shl_stdout_ok = false; warningf(true, Tf_sD_s, s->file, cstrerror(errno)); /* mandated by SUSv4 */ exstat = 127; unwind(LERROR); } kshname = s->file; } else { Flag(FSTDIN) = 1; s = pushs(SSTDIN, ATEMP); s->file = "<stdin>"; s->u.shf = shf_fdopen(0, SHF_RD | can_seek(0), NULL); if (isatty(0) && isatty(2)) { Flag(FTALKING) = Flag(FTALKING_I) = 1; /* The following only if isatty(0) */ s->flags |= SF_TTY; s->u.shf->flags |= SHF_INTERRUPT; s->file = NULL; } } /* this bizarreness is mandated by POSIX */ if (fstat(0, &s_stdin) >= 0 && S_ISCHR(s_stdin.st_mode) && Flag(FTALKING)) reset_nonblock(0); /* initialise job control */ j_init(); /* do this after j_init() which calls tty_init_state() */ if (Flag(FTALKING)) { if (utf_flag == 2) { #ifndef MKSH_ASSUME_UTF8 /* auto-detect from locale or environment */ utf_flag = 4; #else /* this may not be an #elif */ #if MKSH_ASSUME_UTF8 utf_flag = 1; #else /* always disable UTF-8 (for interactive) */ utf_flag = 0; #endif #endif } #ifndef MKSH_NO_CMDLINE_EDITING x_init(); #endif } #ifdef SIGWINCH sigtraps[SIGWINCH].flags |= TF_SHELL_USES; setsig(&sigtraps[SIGWINCH], x_sigwinch, SS_RESTORE_ORIG|SS_FORCE|SS_SHTRAP); #endif l = e->loc; if (Flag(FAS_BUILTIN)) { l->argc = argc; l->argv = argv; l->argv[0] = ccp; } else { l->argc = argc - argi; /* * allocate a new array because otherwise, when we modify * it in-place, ps(1) output changes; the meaning of argc * here is slightly different as it excludes kshname, and * we add a trailing NULL sentinel as well */ l->argv = alloc2(l->argc + 2, sizeof(void *), APERM); l->argv[0] = kshname; memcpy(&l->argv[1], &argv[argi], l->argc * sizeof(void *)); l->argv[l->argc + 1] = NULL; getopts_reset(1); } /* divine the initial state of the utf8-mode Flag */ ccp = null; switch (utf_flag) { /* auto-detect from locale or environment */ case 4: #if HAVE_SETLOCALE_CTYPE ccp = setlocale(LC_CTYPE, ""); #if HAVE_LANGINFO_CODESET if (!isuc(ccp)) ccp = nl_langinfo(CODESET); #endif if (!isuc(ccp)) ccp = null; #endif /* FALLTHROUGH */ /* auto-detect from environment */ case 3: /* these were imported from environ earlier */ if (ccp == null) ccp = str_val(global("LC_ALL")); if (ccp == null) ccp = str_val(global("LC_CTYPE")); if (ccp == null) ccp = str_val(global("LANG")); UTFMODE = isuc(ccp); break; /* not set on command line, not FTALKING */ case 2: /* unknown values */ default: utf_flag = 0; /* FALLTHROUGH */ /* known values */ case 1: case 0: UTFMODE = utf_flag; break; } /* Disable during .profile/ENV reading */ restricted_shell = Flag(FRESTRICTED); Flag(FRESTRICTED) = 0; errexit = Flag(FERREXIT); Flag(FERREXIT) = 0; /* * Do this before profile/$ENV so that if it causes problems in them, * user will know why things broke. */ if (!current_wd[0] && Flag(FTALKING)) warningf(false, "can't determine current directory"); if (Flag(FLOGIN)) include(MKSH_SYSTEM_PROFILE, 0, NULL, true); if (!Flag(FPRIVILEGED)) { if (Flag(FLOGIN)) include(substitute("$HOME/.profile", 0), 0, NULL, true); if (Flag(FTALKING)) { cp = substitute("${ENV:-" MKSHRC_PATH "}", DOTILDE); if (cp[0] != '\0') include(cp, 0, NULL, true); } } else { include(MKSH_SUID_PROFILE, 0, NULL, true); /* turn off -p if not set explicitly */ if (Flag(FPRIVILEGED) != 1) change_flag(FPRIVILEGED, OF_INTERNAL, false); } if (restricted_shell) { c_builtin(restr_com); /* After typeset command... */ Flag(FRESTRICTED) = 1; } Flag(FERREXIT) = errexit; if (Flag(FTALKING) && s) hist_init(s); else /* set after ENV */ Flag(FTRACKALL) = 1; alarm_init(); *sp = s; *lp = l; return (0); }
static int comexec(struct op *t, struct tbl * volatile tp, const char **ap, volatile int flags, volatile int *xerrok) { int i; volatile int rv = 0; const char *cp; const char **lastp; /* Must be static (XXX but why?) */ static struct op texec; int type_flags; bool keepasn_ok; int fcflags = FC_BI|FC_FUNC|FC_PATH; bool bourne_function_call = false; struct block *l_expand, *l_assign; /* * snag the last argument for $_ XXX not the same as AT&T ksh, * which only seems to set $_ after a newline (but not in * functions/dot scripts, but in interactive and script) - * perhaps save last arg here and set it in shell()?. */ if (Flag(FTALKING) && *(lastp = ap)) { while (*++lastp) ; /* setstr() can't fail here */ setstr(typeset("_", LOCAL, 0, INTEGER, 0), *--lastp, KSH_RETURN_ERROR); } /** * Deal with the shell builtins builtin, exec and command since * they can be followed by other commands. This must be done before * we know if we should create a local block which must be done * before we can do a path search (in case the assignments change * PATH). * Odd cases: * FOO=bar exec >/dev/null FOO is kept but not exported * FOO=bar exec foobar FOO is exported * FOO=bar command exec >/dev/null FOO is neither kept nor exported * FOO=bar command FOO is neither kept nor exported * PATH=... foobar use new PATH in foobar search */ keepasn_ok = true; while (tp && tp->type == CSHELL) { /* undo effects of command */ fcflags = FC_BI|FC_FUNC|FC_PATH; if (tp->val.f == c_builtin) { if ((cp = *++ap) == NULL || (!strcmp(cp, "--") && (cp = *++ap) == NULL)) { tp = NULL; break; } if ((tp = findcom(cp, FC_BI)) == NULL) errorf("%s: %s: %s", Tbuiltin, cp, "not a builtin"); continue; } else if (tp->val.f == c_exec) { if (ap[1] == NULL) break; ap++; flags |= XEXEC; } else if (tp->val.f == c_command) { int optc, saw_p = 0; /* * Ugly dealing with options in two places (here * and in c_command(), but such is life) */ ksh_getopt_reset(&builtin_opt, 0); while ((optc = ksh_getopt(ap, &builtin_opt, ":p")) == 'p') saw_p = 1; if (optc != EOF) /* command -vV or something */ break; /* don't look for functions */ fcflags = FC_BI|FC_PATH; if (saw_p) { if (Flag(FRESTRICTED)) { warningf(true, "%s: %s", "command -p", "restricted"); rv = 1; goto Leave; } fcflags |= FC_DEFPATH; } ap += builtin_opt.optind; /* * POSIX says special builtins lose their status * if accessed using command. */ keepasn_ok = false; if (!ap[0]) { /* ensure command with no args exits with 0 */ subst_exstat = 0; break; } #ifndef MKSH_NO_EXTERNAL_CAT } else if (tp->val.f == c_cat) { /* * if we have any flags, do not use the builtin * in theory, we could allow -u, but that would * mean to use ksh_getopt here and possibly ad- * ded complexity and more code and isn't worth * additional hassle (and the builtin must call * ksh_getopt already but can't come back here) */ if (ap[1] && ap[1][0] == '-' && ap[1][1] != '\0' && /* argument, begins with -, is not - or -- */ (ap[1][1] != '-' || ap[1][2] != '\0')) /* don't look for builtins or functions */ fcflags = FC_PATH; else /* go on, use the builtin */ break; #endif #if !defined(MKSH_SMALL) } else if (tp->val.f == c_trap) { t->u.evalflags &= ~DOTCOMEXEC; break; #endif } else break; tp = findcom(ap[0], fcflags & (FC_BI|FC_FUNC)); } #if !defined(MKSH_SMALL) if (t->u.evalflags & DOTCOMEXEC) flags |= XEXEC; #endif l_expand = e->loc; if (keepasn_ok && (!ap[0] || (tp && (tp->flag & KEEPASN)))) type_flags = 0; else { /* create new variable/function block */ newblock(); /* ksh functions don't keep assignments, POSIX functions do. */ if (keepasn_ok && tp && tp->type == CFUNC && !(tp->flag & FKSH)) { bourne_function_call = true; type_flags = EXPORT; } else type_flags = LOCAL|LOCAL_COPY|EXPORT; } l_assign = e->loc; if (Flag(FEXPORT)) type_flags |= EXPORT; for (i = 0; t->vars[i]; i++) { /* do NOT lookup in the new var/fn block just created */ e->loc = l_expand; cp = evalstr(t->vars[i], DOASNTILDE); e->loc = l_assign; /* but assign in there as usual */ if (Flag(FXTRACE)) { if (i == 0) shf_puts(substitute(str_val(global("PS4")), 0), shl_out); shf_fprintf(shl_out, "%s%c", cp, t->vars[i + 1] ? ' ' : '\n'); if (!t->vars[i + 1]) shf_flush(shl_out); } typeset(cp, type_flags, 0, 0, 0); if (bourne_function_call && !(type_flags & EXPORT)) typeset(cp, LOCAL|LOCAL_COPY|EXPORT, 0, 0, 0); } if ((cp = *ap) == NULL) { rv = subst_exstat; goto Leave; } else if (!tp) { if (Flag(FRESTRICTED) && vstrchr(cp, '/')) { warningf(true, "%s: %s", cp, "restricted"); rv = 1; goto Leave; } tp = findcom(cp, fcflags); } switch (tp->type) { /* shell built-in */ case CSHELL: rv = call_builtin(tp, (const char **)ap, null); if (!keepasn_ok && tp->val.f == c_shift) { l_expand->argc = l_assign->argc; l_expand->argv = l_assign->argv; } break; /* function call */ case CFUNC: { volatile unsigned char old_xflag; volatile uint32_t old_inuse; const char * volatile old_kshname; if (!(tp->flag & ISSET)) { struct tbl *ftp; if (!tp->u.fpath) { rv = (tp->u2.errnov == ENOENT) ? 127 : 126; warningf(true, "%s: %s %s: %s", cp, "can't find", "function definition file", cstrerror(tp->u2.errnov)); break; } if (include(tp->u.fpath, 0, NULL, false) < 0) { rv = errno; warningf(true, "%s: %s %s %s: %s", cp, "can't open", "function definition file", tp->u.fpath, cstrerror(rv)); rv = 127; break; } if (!(ftp = findfunc(cp, hash(cp), false)) || !(ftp->flag & ISSET)) { warningf(true, "%s: %s %s", cp, "function not defined by", tp->u.fpath); rv = 127; break; } tp = ftp; } /* * ksh functions set $0 to function name, POSIX * functions leave $0 unchanged. */ old_kshname = kshname; if (tp->flag & FKSH) kshname = ap[0]; else ap[0] = kshname; e->loc->argv = ap; for (i = 0; *ap++ != NULL; i++) ; e->loc->argc = i - 1; /* * ksh-style functions handle getopts sanely, * Bourne/POSIX functions are insane... */ if (tp->flag & FKSH) { e->loc->flags |= BF_DOGETOPTS; e->loc->getopts_state = user_opt; getopts_reset(1); } old_xflag = Flag(FXTRACE); Flag(FXTRACE) |= tp->flag & TRACE ? 1 : 0; old_inuse = tp->flag & FINUSE; tp->flag |= FINUSE; e->type = E_FUNC; if (!(i = kshsetjmp(e->jbuf))) { execute(tp->val.t, flags & XERROK, NULL); i = LRETURN; } kshname = old_kshname; Flag(FXTRACE) = old_xflag; tp->flag = (tp->flag & ~FINUSE) | old_inuse; /* * Were we deleted while executing? If so, free the * execution tree. TODO: Unfortunately, the table entry * is never re-used until the lookup table is expanded. */ if ((tp->flag & (FDELETE|FINUSE)) == FDELETE) { if (tp->flag & ALLOC) { tp->flag &= ~ALLOC; tfree(tp->val.t, tp->areap); } tp->flag = 0; } switch (i) { case LRETURN: case LERROR: rv = exstat & 0xFF; break; case LINTR: case LEXIT: case LLEAVE: case LSHELL: quitenv(NULL); unwind(i); /* NOTREACHED */ default: quitenv(NULL); internal_errorf("%s %d", "CFUNC", i); } break; } /* executable command */ case CEXEC: /* tracked alias */ case CTALIAS: if (!(tp->flag&ISSET)) { if (tp->u2.errnov == ENOENT) { rv = 127; warningf(true, "%s: %s", cp, "not found"); } else { rv = 126; warningf(true, "%s: %s: %s", cp, "can't execute", cstrerror(tp->u2.errnov)); } break; } /* set $_ to programme's full path */ /* setstr() can't fail here */ setstr(typeset("_", LOCAL|EXPORT, 0, INTEGER, 0), tp->val.s, KSH_RETURN_ERROR); if (flags&XEXEC) { j_exit(); if (!(flags&XBGND) #ifndef MKSH_UNEMPLOYED || Flag(FMONITOR) #endif ) { setexecsig(&sigtraps[SIGINT], SS_RESTORE_ORIG); setexecsig(&sigtraps[SIGQUIT], SS_RESTORE_ORIG); } } /* to fork we set up a TEXEC node and call execute */ texec.type = TEXEC; /* for tprint */ texec.left = t; texec.str = tp->val.s; texec.args = ap; rv = exchild(&texec, flags, xerrok, -1); break; } Leave: if (flags & XEXEC) { exstat = rv & 0xFF; unwind(LLEAVE); } return (rv); }
int main(int argc, char *argv[]) { register int i; int argi; Source *s; struct block *l; int restricted, errexit; char **wp; struct env env; pid_t ppid; #ifdef MEM_DEBUG chmem_set_defaults("ct", 1); /* chmem_push("+c", 1); */ #endif /* MEM_DEBUG */ #ifdef OS2 setmode (0, O_BINARY); setmode (1, O_TEXT); #endif /* make sure argv[] is sane */ if (!*argv) { static const char *empty_argv[] = { "pdksh", (char *) 0 }; argv = (char **)__UNCONST(empty_argv); argc = 1; } kshname = *argv; ainit(&aperm); /* initialize permanent Area */ /* set up base environment */ memset(&env, 0, sizeof(env)); env.type = E_NONE; ainit(&env.area); e = &env; newblock(); /* set up global l->vars and l->funs */ /* Do this first so output routines (eg, errorf, shellf) can work */ initio(); initvar(); initctypes(); inittraps(); #ifdef KSH coproc_init(); #endif /* KSH */ /* set up variable and command dictionaries */ tinit(&taliases, APERM, 0); tinit(&aliases, APERM, 0); tinit(&homedirs, APERM, 0); /* define shell keywords */ initkeywords(); /* define built-in commands */ tinit(&builtins, APERM, 64); /* must be 2^n (currently 40 builtins) */ for (i = 0; shbuiltins[i].name != NULL; i++) builtin(shbuiltins[i].name, shbuiltins[i].func); for (i = 0; kshbuiltins[i].name != NULL; i++) builtin(kshbuiltins[i].name, kshbuiltins[i].func); init_histvec(); def_path = DEFAULT__PATH; #if defined(HAVE_CONFSTR) && defined(_CS_PATH) { size_t len = confstr(_CS_PATH, (char *) 0, 0); char *new; if (len > 0) { confstr(_CS_PATH, new = alloc(len + 1, APERM), len + 1); def_path = new; } }