void cut(void) { if (1 & (h * w)) return; hor = alloc2(w + 1, h + 1); ver = alloc2(w + 1, h + 1); vis = alloc2(w + 1, h + 1); if (h & 1) { ver[h/2][w/2] = 1; walk(h / 2, w / 2); } else if (w & 1) { hor[h/2][w/2] = 1; walk(h / 2, w / 2); } else { vis[h/2][w/2] = 1; hor[h/2][w/2-1] = hor[h/2][w/2] = 1; walk(h / 2, w / 2 - 1); hor[h/2][w/2-1] = hor[h/2][w/2] = 0; ver[h/2 - 1][w/2] = ver[h/2][w/2] = 1; walk(h / 2 - 1, w/2); } }
void count_only(void) { int t; long res; if (h * w & 1) return; if (h & 1) t = h, h = w, w = t; vis = alloc2(w + 1, h + 1); vis[h/2][w/2] = 1; if (w & 1) vis[h/2][w/2 + 1] = 1; if (w > 1) { cwalk(h/2, w/2 - 1, 1); res = 2 * count - 1; count = 0; if (w != h) cwalk(h/2+1, w/2, (w & 1) ? 3 : 2); res += 2 * count - !(w & 1); } else { res = 1; } if (w == h) res = 2 * res + 2; count = res; }
int main() { typedef rt::node_allocator_lazy<int> inner_alloc_type; typedef std::list<int, inner_alloc_type> inner_list_type; typedef std::scoped_allocator_adaptor< rt::node_allocator_lazy<inner_list_type> , inner_alloc_type> outer_alloc_type; typedef std::list<inner_list_type, outer_alloc_type> outer_list_type; std::array<char, 2000> buffer1 = {{}}; std::array<char, 2000> buffer2 = {{}}; rt::node_alloc_header header1(buffer1); rt::node_alloc_header header2(buffer2); inner_alloc_type alloc1(&header1); rt::node_allocator_lazy<inner_list_type> alloc2(&header2); outer_alloc_type alloc(alloc2, alloc1); outer_list_type t1(alloc); t1.push_back({{5, 3, 7, 20}, alloc1}); t1.push_back({{1, 44, 22, 8}, alloc1}); rt::print(t1.front()); rt::print(t1.back()); }
main() { int i,j,*ipvt,info,n=N; double **a,*b,*z,rcond; a = (double**)alloc2(n,n,sizeof(double)); ipvt = (int*)alloc1(n,sizeof(int)); b = (double*)alloc1(n,sizeof(double)); z = (double*)alloc1(n,sizeof(double)); /* Examples 3.6 & 3.7 from Kahaner, Moler, and Nash */ a[0][0] = 9.7; a[1][0] = 6.6; a[0][1] = 4.1; a[1][1] = 2.8; b[0] = 9.70; b[1] = 4.11; /* dgefa(a,n,ipvt,&info); printf("info = %d\n",info); */ dgeco(a,n,ipvt,&rcond,z); printf("rcond = %g\n",rcond); printf("condition number estimate = %g\n",1.0/rcond); printf("number of significant figures = %d\n", (int)log10(rcond/DBL_EPSILON)); dgesl(a,n,ipvt,b,0); pvecd(n,b); }
void free_list_test() { std::ostringstream os; typedef falcon::free_list<A, test_allocator<A> > free_list_type; free_list_type alloc(1, os); A * a1 = alloc.alloc(); CHECK_EQUAL_VALUE("alloc\n", os.str()); alloc.free(a1); A * a2 = alloc.alloc(); CHECK_EQUAL_VALUE("alloc\n", os.str()); A * a3 = alloc.alloc(); CHECK_EQUAL_VALUE("alloc\nalloc\n", os.str()); alloc.free(a2); A * a4 = alloc.alloc(); CHECK_EQUAL_VALUE("alloc\nalloc\n", os.str()); alloc.free(a4); alloc.free(a3); CHECK_EQUAL_VALUE("alloc\nalloc\n", os.str()); free_list_type alloc2(1, os); alloc2.free(alloc2.alloc()); CHECK_EQUAL_VALUE("alloc\nalloc\nalloc\n", os.str()); alloc.merge(alloc2); alloc.clear(); CHECK_EQUAL_VALUE("alloc\nalloc\nalloc\ndealloc\ndealloc\ndealloc\n", os.str()); alloc2.clear(); CHECK_EQUAL_VALUE("alloc\nalloc\nalloc\ndealloc\ndealloc\ndealloc\n", os.str()); }
void allocator() { aa_mem_region_t reg; aa_mem_region_init( ®, 1024 ); /*--- List ---*/ amino::RegionList<int>::allocator alloc(®); amino::RegionList<int>::type list(alloc); list.push_back(1); list.push_back(2); list.push_back(3); printf("List:\n"); for( amino::RegionList<int>::iterator p = list.begin(); p != list.end(); p++ ) { printf("> %d\n", *p); } /*--- Vector ---*/ amino::RegionVector<int>::allocator alloc1(®); amino::RegionVector<int>::type vector(3, 0, alloc1); vector[0] = 10; vector[1] = 20; vector[2] = 30; printf("Vector:\n"); for( amino::RegionVector<int>::iterator p = vector.begin(); p != vector.end(); p++ ) { printf("> %d\n", *p); } /*--- Map ---*/ amino::RegionMap<int,int>::allocator alloc2(®); amino::RegionMap<int,int>::type map(std::less<int>(), alloc2); map[1] = 10; map[2] = 20; map[3] = 30; printf("Map:\n> %d %d %d\n", map[1], map[2], map[3] ); /*--- Stats ---*/ printf("Stats:\n" "> start: 0x%lx\n" "> head: 0x%lx\n" "> used: %lu\n", (intptr_t)reg.node->d, (intptr_t)reg.head, (intptr_t)reg.head - (intptr_t)reg.node->d ); aa_mem_region_destroy( ® ); }
static Lex_state * push_state_i(State_info *si, Lex_state *old_end) { Lex_state *news = alloc2(STATE_BSIZE, sizeof(Lex_state), ATEMP); news[0].ls_base = old_end; si->base = &news[0]; si->end = &news[STATE_BSIZE]; return (&news[1]); }
static CharAE *new_empty_CharAE() { CharAE *ae; if (use_malloc && CharAE_pool_len >= CHARAE_POOL_MAXLEN) error("S4Vectors internal error in new_empty_CharAE(): " "CharAE pool is full"); ae = (CharAE *) alloc2(1, sizeof(CharAE)); ae->_buflength = ae->_nelt = 0; if (use_malloc) CharAE_pool[CharAE_pool_len++] = ae; return ae; }
static LLongAE *new_empty_LLongAE() { LLongAE *ae; if (use_malloc && LLongAE_pool_len >= LLONGAE_POOL_MAXLEN) error("S4Vectors internal error in new_empty_LLongAE(): " "LLongAE pool is full"); ae = (LLongAE *) alloc2(1, sizeof(LLongAE)); ae->_buflength = ae->_nelt = 0; if (use_malloc) LLongAE_pool[LLongAE_pool_len++] = ae; return ae; }
static IntPairAEAE *new_empty_IntPairAEAE() { IntPairAEAE *aeae; if (use_malloc && IntPairAEAE_pool_len >= INTPAIRAEAE_POOL_MAXLEN) error("S4Vectors internal error in new_empty_IntPairAEAE(): " "IntPairAEAE pool is full"); aeae = (IntPairAEAE *) alloc2(1, sizeof(IntPairAEAE)); aeae->_buflength = aeae->_nelt = 0; if (use_malloc) IntPairAEAE_pool[IntPairAEAE_pool_len++] = aeae; return aeae; }
struct node_top* create_sll(void) { struct node_top *sll = alloc1(); struct node_top *now = sll; // NOTE: running this on bare metal may cause the machine to swap a bit int i; for (i = 1; i; ++i) { now->next = alloc2(); now = now->next; now->next = alloc1(); now = now->next; } return sll; }
TEST(allocator_test, standard) { // default constructor misc::pool_alloc<int>MISC_TALIAS alloc1; // copy constructor misc::pool_alloc<int>MISC_TALIAS alloc2(alloc1); // template constructor misc::pool_alloc<double>MISC_TALIAS alloc3(alloc2); // operator == EXPECT_TRUE(alloc1 == alloc2); // operator != #ifdef MISC_STL_LIBSTDCXX EXPECT_FALSE(alloc1 != alloc2); // TODO: why not support different types? #elif defined(MISC_STL_VC) EXPECT_FALSE(alloc1 != alloc3); #endif }
static void tgrow(struct table *tp) { size_t i, j, osize, mask, perturb; struct tbl *tblp, **pp; struct tbl **ntblp, **otblp = tp->tbls; if (tp->tshift > 29) internal_errorf("hash table size limit reached"); /* calculate old size, new shift and new size */ osize = (size_t)1 << (tp->tshift++); i = osize << 1; ntblp = alloc2(i, sizeof(struct tbl *), tp->areap); /* multiplication cannot overflow: alloc2 checked that */ memset(ntblp, 0, i * sizeof(struct tbl *)); /* table can get very full when reaching its size limit */ tp->nfree = (tp->tshift == 30) ? 0x3FFF0000UL : /* but otherwise, only 75% */ ((i * 3) / 4); tp->tbls = ntblp; if (otblp == NULL) return; mask = i - 1; for (i = 0; i < osize; i++) if ((tblp = otblp[i]) != NULL) { if ((tblp->flag & DEFINED)) { /* search for free hash table slot */ j = perturb = tblp->ua.hval; goto find_first_empty_slot; find_next_empty_slot: j = (j << 2) + j + perturb + 1; perturb >>= PERTURB_SHIFT; find_first_empty_slot: pp = &ntblp[j & mask]; if (*pp != NULL) goto find_next_empty_slot; /* found an empty hash table slot */ *pp = tblp; tp->nfree--; } else if (!(tblp->flag & FINUSE)) {
void test_mark_address_returns_forwarding_pointer() { immix::Block& block = gc->get_block(); immix::SingleBlockAllocator alloc(block); memory::Address addr = alloc.allocate(24); // Clear out fwd to be sure it's not set addr.as<SimpleObject>()->fwd = 0; immix::Block& block2 = gc->get_block(); immix::SingleBlockAllocator alloc2(block2); memory::Address addr2 = alloc2.allocate(24); gc->describer().set_forwarding_pointer(addr, addr2); memory::Address out = gc->mark_address(addr, alloc); TS_ASSERT_EQUALS(addr.as<SimpleObject>()->fwd, addr2); TS_ASSERT_EQUALS(out, addr2); }
bool test_deallocate() { const std::size_t ptr_size = sizeof (char*); const std::size_t data_size = sizeof (std::size_t); std::array<char, 3 * data_size> buffer = {{}}; rt::node_alloc_header header(buffer); rt::node_allocator_lazy<int> alloc1(&header); // links the node_allocator_lazy. rt::node_allocator_lazy<std::size_t> alloc2(alloc1); std::size_t* p1 = alloc2.allocate_node(); *p1 = 10; // To avoid a warning. std::size_t* p2 = alloc2.allocate_node(); try { std::size_t* p3 = alloc2.allocate_node(); // Should throw. *p3 = 100; // To avoid a warning. return false; } catch (...) { alloc2.deallocate_node(p2); } return true; }
/* 'new_nmemb' must be > 'old_nmemb'. */ static void *realloc2(void *ptr, int new_nmemb, int old_nmemb, size_t size) { void *new_ptr; if (new_nmemb <= old_nmemb) error("S4Vectors internal error in realloc2(): " "'new_nmemb' <= 'old_nmemb'"); if (old_nmemb == 0) return alloc2(new_nmemb, size); if (use_malloc) { //printf("realloc2: new_nmemb=%d old_nmemb=%d\n", // new_nmemb, old_nmemb); size *= new_nmemb; new_ptr = realloc(ptr, size); if (new_ptr == NULL) error("S4Vectors internal error in realloc2(): " "cannot reallocate memory"); } else { new_ptr = (void *) R_alloc(size, new_nmemb); memcpy(new_ptr, ptr, size * old_nmemb); } return new_ptr; }
static IntPairAE *new_empty_IntPairAE() { IntAE *a, *b; IntPairAE *ae; if (use_malloc && IntPairAE_pool_len >= INTPAIRAE_POOL_MAXLEN) error("S4Vectors internal error in new_empty_IntPairAE(): " "IntPairAE pool is full"); a = new_empty_IntAE(); b = new_empty_IntAE(); ae = (IntPairAE *) alloc2(1, sizeof(IntPairAE)); ae->a = a; ae->b = b; if (use_malloc) { if (remove_from_IntAE_pool(a) == -1 || remove_from_IntAE_pool(b) == -1) error("S4Vectors internal error " "in new_empty_IntPairAE(): " "IntAEs to stick in IntPairAE cannot be found " "in pool for removal"); IntPairAE_pool[IntPairAE_pool_len++] = ae; } return ae; }
/* * execute command tree */ int execute(struct op * volatile t, /* if XEXEC don't fork */ volatile int flags, volatile int * volatile xerrok) { int i; volatile int rv = 0, dummy = 0; int pv[2]; const char ** volatile ap = NULL; char ** volatile up; const char *s, *ccp; struct ioword **iowp; struct tbl *tp = NULL; char *cp; if (t == NULL) return (0); /* Caller doesn't care if XERROK should propagate. */ if (xerrok == NULL) xerrok = &dummy; if ((flags&XFORK) && !(flags&XEXEC) && t->type != TPIPE) /* run in sub-process */ return (exchild(t, flags & ~XTIME, xerrok, -1)); newenv(E_EXEC); if (trap) runtraps(0); /* we want to run an executable, do some variance checks */ if (t->type == TCOM) { /* check if this is 'var=<<EOF' */ if ( /* we have zero arguments, i.e. no programme to run */ t->args[0] == NULL && /* we have exactly one variable assignment */ t->vars[0] != NULL && t->vars[1] == NULL && /* we have exactly one I/O redirection */ t->ioact != NULL && t->ioact[0] != NULL && t->ioact[1] == NULL && /* of type "here document" (or "here string") */ (t->ioact[0]->flag & IOTYPE) == IOHERE && /* the variable assignment begins with a valid varname */ (ccp = skip_wdvarname(t->vars[0], true)) != t->vars[0] && /* and has no right-hand side (i.e. "varname=") */ ccp[0] == CHAR && ccp[1] == '=' && ccp[2] == EOS && /* plus we can have a here document content */ herein(t->ioact[0], &cp) == 0 && cp && *cp) { char *sp = cp, *dp; size_t n = ccp - t->vars[0] + 2, z; /* drop redirection (will be garbage collected) */ t->ioact = NULL; /* set variable to its expanded value */ z = strlen(cp) + 1; if (notoktomul(z, 2) || notoktoadd(z * 2, n)) internal_errorf(Toomem, (unsigned long)-1); dp = alloc(z * 2 + n, ATEMP); memcpy(dp, t->vars[0], n); t->vars[0] = dp; dp += n; while (*sp) { *dp++ = QCHAR; *dp++ = *sp++; } *dp = EOS; /* free the expanded value */ afree(cp, APERM); } /* * Clear subst_exstat before argument expansion. Used by * null commands (see comexec() and c_eval()) and by c_set(). */ subst_exstat = 0; /* for $LINENO */ current_lineno = t->lineno; /* * POSIX says expand command words first, then redirections, * and assignments last.. */ up = eval(t->args, t->u.evalflags | DOBLANK | DOGLOB | DOTILDE); if (flags & XTIME) /* Allow option parsing (bizarre, but POSIX) */ timex_hook(t, &up); ap = (const char **)up; if (Flag(FXTRACE) && ap[0]) { shf_puts(substitute(str_val(global("PS4")), 0), shl_out); for (i = 0; ap[i]; i++) shf_fprintf(shl_out, "%s%c", ap[i], ap[i + 1] ? ' ' : '\n'); shf_flush(shl_out); } if (ap[0]) tp = findcom(ap[0], FC_BI|FC_FUNC); } flags &= ~XTIME; if (t->ioact != NULL || t->type == TPIPE || t->type == TCOPROC) { e->savefd = alloc2(NUFILE, sizeof(short), ATEMP); /* initialise to not redirected */ memset(e->savefd, 0, NUFILE * sizeof(short)); } /* mark for replacement later (unless TPIPE) */ vp_pipest->flag |= INT_L; /* do redirection, to be restored in quitenv() */ if (t->ioact != NULL) for (iowp = t->ioact; *iowp != NULL; iowp++) { if (iosetup(*iowp, tp) < 0) { exstat = rv = 1; /* * Redirection failures for special commands * cause (non-interactive) shell to exit. */ if (tp && tp->type == CSHELL && (tp->flag & SPEC_BI)) errorfz(); /* Deal with FERREXIT, quitenv(), etc. */ goto Break; } } switch (t->type) { case TCOM: rv = comexec(t, tp, (const char **)ap, flags, xerrok); break; case TPAREN: rv = execute(t->left, flags | XFORK, xerrok); break; case TPIPE: flags |= XFORK; flags &= ~XEXEC; e->savefd[0] = savefd(0); e->savefd[1] = savefd(1); while (t->type == TPIPE) { openpipe(pv); /* stdout of curr */ ksh_dup2(pv[1], 1, false); /** * Let exchild() close pv[0] in child * (if this isn't done, commands like * (: ; cat /etc/termcap) | sleep 1 * will hang forever). */ exchild(t->left, flags | XPIPEO | XCCLOSE, NULL, pv[0]); /* stdin of next */ ksh_dup2(pv[0], 0, false); closepipe(pv); flags |= XPIPEI; t = t->right; } /* stdout of last */ restfd(1, e->savefd[1]); /* no need to re-restore this */ e->savefd[1] = 0; /* Let exchild() close 0 in parent, after fork, before wait */ i = exchild(t, flags | XPCLOSE | XPIPEST, xerrok, 0); if (!(flags&XBGND) && !(flags&XXCOM)) rv = i; break; case TLIST: while (t->type == TLIST) { execute(t->left, flags & XERROK, NULL); t = t->right; } rv = execute(t, flags & XERROK, xerrok); break; case TCOPROC: { #ifndef MKSH_NOPROSPECTOFWORK sigset_t omask; /* * Block sigchild as we are using things changed in the * signal handler */ sigprocmask(SIG_BLOCK, &sm_sigchld, &omask); e->type = E_ERRH; if ((i = kshsetjmp(e->jbuf))) { sigprocmask(SIG_SETMASK, &omask, NULL); quitenv(NULL); unwind(i); /* NOTREACHED */ } #endif /* Already have a (live) co-process? */ if (coproc.job && coproc.write >= 0) errorf("coprocess already exists"); /* Can we re-use the existing co-process pipe? */ coproc_cleanup(true); /* do this before opening pipes, in case these fail */ e->savefd[0] = savefd(0); e->savefd[1] = savefd(1); openpipe(pv); if (pv[0] != 0) { ksh_dup2(pv[0], 0, false); close(pv[0]); } coproc.write = pv[1]; coproc.job = NULL; if (coproc.readw >= 0) ksh_dup2(coproc.readw, 1, false); else { openpipe(pv); coproc.read = pv[0]; ksh_dup2(pv[1], 1, false); /* closed before first read */ coproc.readw = pv[1]; coproc.njobs = 0; /* create new coprocess id */ ++coproc.id; } #ifndef MKSH_NOPROSPECTOFWORK sigprocmask(SIG_SETMASK, &omask, NULL); /* no more need for error handler */ e->type = E_EXEC; #endif /* * exchild() closes coproc.* in child after fork, * will also increment coproc.njobs when the * job is actually created. */ flags &= ~XEXEC; exchild(t->left, flags | XBGND | XFORK | XCOPROC | XCCLOSE, NULL, coproc.readw); break; } case TASYNC: /* * XXX non-optimal, I think - "(foo &)", forks for (), * forks again for async... parent should optimise * this to "foo &"... */ rv = execute(t->left, (flags&~XEXEC)|XBGND|XFORK, xerrok); break; case TOR: case TAND: rv = execute(t->left, XERROK, xerrok); if ((rv == 0) == (t->type == TAND)) rv = execute(t->right, XERROK, xerrok); flags |= XERROK; if (xerrok) *xerrok = 1; break; case TBANG: rv = !execute(t->right, XERROK, xerrok); flags |= XERROK; if (xerrok) *xerrok = 1; break; case TDBRACKET: { Test_env te; te.flags = TEF_DBRACKET; te.pos.wp = t->args; te.isa = dbteste_isa; te.getopnd = dbteste_getopnd; te.eval = test_eval; te.error = dbteste_error; rv = test_parse(&te); break; } case TFOR: case TSELECT: { volatile bool is_first = true; ap = (t->vars == NULL) ? e->loc->argv + 1 : (const char **)eval((const char **)t->vars, DOBLANK | DOGLOB | DOTILDE); e->type = E_LOOP; while ((i = kshsetjmp(e->jbuf))) { if ((e->flags&EF_BRKCONT_PASS) || (i != LBREAK && i != LCONTIN)) { quitenv(NULL); unwind(i); } else if (i == LBREAK) { rv = 0; goto Break; } } /* in case of a continue */ rv = 0; if (t->type == TFOR) { while (*ap != NULL) { setstr(global(t->str), *ap++, KSH_UNWIND_ERROR); rv = execute(t->left, flags & XERROK, xerrok); } } else { /* TSELECT */ for (;;) { if (!(ccp = do_selectargs(ap, is_first))) { rv = 1; break; } is_first = false; setstr(global(t->str), ccp, KSH_UNWIND_ERROR); execute(t->left, flags & XERROK, xerrok); } } break; } case TWHILE: case TUNTIL: e->type = E_LOOP; while ((i = kshsetjmp(e->jbuf))) { if ((e->flags&EF_BRKCONT_PASS) || (i != LBREAK && i != LCONTIN)) { quitenv(NULL); unwind(i); } else if (i == LBREAK) { rv = 0; goto Break; } } /* in case of a continue */ rv = 0; while ((execute(t->left, XERROK, NULL) == 0) == (t->type == TWHILE)) rv = execute(t->right, flags & XERROK, xerrok); break; case TIF: case TELIF: if (t->right == NULL) /* should be error */ break; rv = execute(t->left, XERROK, NULL) == 0 ? execute(t->right->left, flags & XERROK, xerrok) : execute(t->right->right, flags & XERROK, xerrok); break; case TCASE: i = 0; ccp = evalstr(t->str, DOTILDE); for (t = t->left; t != NULL && t->type == TPAT; t = t->right) { for (ap = (const char **)t->vars; *ap; ap++) { if (i || ((s = evalstr(*ap, DOTILDE|DOPAT)) && gmatchx(ccp, s, false))) { rv = execute(t->left, flags & XERROK, xerrok); i = 0; switch (t->u.charflag) { case '&': i = 1; /* FALLTHROUGH */ case '|': goto TCASE_next; } goto TCASE_out; } } i = 0; TCASE_next: /* empty */; } TCASE_out: break; case TBRACE: rv = execute(t->left, flags & XERROK, xerrok); break; case TFUNCT: rv = define(t->str, t); break; case TTIME: /* * Clear XEXEC so nested execute() call doesn't exit * (allows "ls -l | time grep foo"). */ rv = timex(t, flags & ~XEXEC, xerrok); break; case TEXEC: /* an eval'd TCOM */ s = t->args[0]; up = makenv(); restoresigs(); cleanup_proc_env(); { union mksh_ccphack cargs; cargs.ro = t->args; execve(t->str, cargs.rw, up); rv = errno; } if (rv == ENOEXEC) scriptexec(t, (const char **)up); else errorf("%s: %s", s, cstrerror(rv)); } Break: exstat = rv & 0xFF; if (vp_pipest->flag & INT_L) { unset(vp_pipest, 1); vp_pipest->flag = DEFINED | ISSET | INTEGER | RDONLY | ARRAY | INT_U; vp_pipest->val.i = rv; } /* restores IO */ quitenv(NULL); if ((flags&XEXEC)) /* exit child */ unwind(LEXIT); if (rv != 0 && !(flags & XERROK) && (xerrok == NULL || !*xerrok)) { if (Flag(FERREXIT) & 0x80) { /* inside eval */ Flag(FERREXIT) = 0; } else { trapsig(ksh_SIGERR); if (Flag(FERREXIT)) unwind(LERROR); } } return (rv); }
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); }