diff options
Diffstat (limited to '')
-rw-r--r-- | src/kash/shinstance.h | 606 |
1 files changed, 606 insertions, 0 deletions
diff --git a/src/kash/shinstance.h b/src/kash/shinstance.h new file mode 100644 index 0000000..f181f33 --- /dev/null +++ b/src/kash/shinstance.h @@ -0,0 +1,606 @@ +/* $Id: shinstance.h 3480 2020-09-21 11:20:56Z bird $ */ +/** @file + * The shell instance and it's methods. + */ + +/* + * Copyright (c) 2007-2010 knut st. osmundsen <bird-kBuild-spamx@anduin.net> + * + * + * This file is part of kBuild. + * + * kBuild is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * kBuild is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with kBuild; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef ___shinstance_h +#define ___shinstance_h + +#include <stdio.h> /* BUFSIZ */ +#include <signal.h> /* NSIG */ +#ifndef _MSC_VER +# include <termios.h> +# include <sys/types.h> +# include <sys/ioctl.h> +# include <sys/resource.h> +#endif +#include <errno.h> +#ifdef _MSC_VER +# define EWOULDBLOCK 140 +#endif + +#include "shtypes.h" +#include "shthread.h" +#include "shfile.h" +#include "shheap.h" +#include "shell.h" +#include "output.h" +#include "options.h" + +#include "expand.h" +#include "exec.h" +#include "var.h" +#include "show.h" + +#ifdef _MSC_VER +# define strcasecmp stricmp +# define strncasecmp strnicmp +#endif + +#ifndef SH_FORKED_MODE +extern shmtx g_sh_exec_inherit_mtx; +#endif + +#ifndef SH_FORKED_MODE +/** + * Subshell status. + */ +typedef struct shsubshellstatus +{ + unsigned volatile refs; /**< Reference counter. */ + int volatile status; /**< The exit code. */ + KBOOL volatile done; /**< Set if done (valid exit code). */ + void *towaiton; /**< Event semaphore / whatever to wait on. */ +# if K_OS == K_OS_WINDOWS + uintptr_t volatile hThread; /**< The thread handle (child closes this). */ +# endif + struct shsubshellstatus *next; /**< Next free one on the free chain. */ +} shsubshellstatus; +#else +struct shsubshellstatus; +#endif + +/** + * A child process. + */ +typedef struct shchild +{ + shpid pid; /**< The pid. */ +#if K_OS == K_OS_WINDOWS + void *hChild; /**< The handle to wait on. */ +#endif +#ifndef SH_FORKED_MODE + shsubshellstatus *subshellstatus; /**< Pointer to the subshell status structure. NULL if child process. */ +#endif +} shchild; + +/* memalloc.c */ +#define MINSIZE 504 /* minimum size of a block */ +struct stack_block { + struct stack_block *prev; + char space[MINSIZE]; +}; + +#ifdef KASH_SEPARATE_PARSER_ALLOCATOR +/** Parser stack allocator block. + * These are reference counted so they can be shared between the parent and + * child shells. They are also using as an alternative to copying function + * definitions, here the final goal is to automatically emit separate + * pstack_blocks for function while parsing to make it more flexible. */ +typedef struct pstack_block { + /** Pointer to the next unallocated byte (= stacknxt). */ + char *nextbyte; + /** Number of bytes available in the current stack block (= stacknleft). */ + size_t avail; + /* Number of chars left for string data (PSTPUTC, PSTUPUTC, et al) (= sstrnleft). */ + size_t strleft; + /** Top of the allocation stack (nextbyte points within this). */ + struct stack_block *top; + /** Size of the top stack element (user space only). */ + size_t topsize; + /** @name statistics + * @{ */ + size_t allocations; + size_t bytesalloced; + size_t nodesalloced; + size_t entriesalloced; + size_t strbytesalloced; + size_t blocks; + size_t fragmentation; + /** @} */ + /** Reference counter. */ + unsigned volatile refs; + /** Whether to make it current when is restored to the top of the stack. */ + KBOOL done; + /** The first stack block. */ + struct stack_block first; +} pstack_block; +#endif + +/* input.c */ +struct strpush { + struct strpush *prev; /* preceding string on stack */ + char *prevstring; + int prevnleft; + int prevlleft; + struct alias *ap; /* if push was associated with an alias */ +}; + +/* + * The parsefile structure pointed to by the global variable parsefile + * contains information about the current file being read. + */ +struct parsefile { + struct parsefile *prev; /* preceding file on stack */ + int linno; /* current line */ + int fd; /* file descriptor (or -1 if string) */ + int nleft; /* number of chars left in this line */ + int lleft; /* number of chars left in this buffer */ + char *nextc; /* next char in buffer */ + char *buf; /* input buffer */ + struct strpush *strpush; /* for pushing strings at this level */ + struct strpush basestrpush; /* so pushing one is fast */ +}; + +/* exec.c */ +#define CMDTABLESIZE 31 /* should be prime */ +#define ARB 1 /* actual size determined at run time */ + +struct tblentry { + struct tblentry *next; /* next entry in hash chain */ + union param param; /* definition of builtin function */ + short cmdtype; /* index identifying command */ + char rehash; /* if set, cd done since entry created */ + char cmdname[ARB]; /* name of command */ +}; + +/* expand.c */ +/* + * Structure specifying which parts of the string should be searched + * for IFS characters. + */ +struct ifsregion { + struct ifsregion *next; /* next region in list */ + int begoff; /* offset of start of region */ + int endoff; /* offset of end of region */ + int inquotes; /* search for nul bytes only */ +}; + +/* redir.c */ +struct redirtab { + struct redirtab *next; + short renamed[10]; +}; + +/** + * This is a replacement for temporary node field nfile.expfname. + * Uses stack allocator, created by expredir(), duplicated by + * subshellinitredir() and popped (but not freed) by expredircleanup(). + */ +typedef struct redirexpfnames +{ + struct redirexpfnames *prev; /**< Previous record. */ + unsigned depth; /**< Nesting depth. */ + unsigned count; /**< Number of expanded filenames in the array. */ + char *names[1]; /**< Variable size. */ +} redirexpfnames; + + +/** + * A shell instance. + * + * This is the core structure of the shell, it contains all + * the data associated with a shell process except that it's + * running in a thread and not a separate process. + */ +struct shinstance +{ + struct shinstance *next; /**< The next shell instance. */ + struct shinstance *prev; /**< The previous shell instance. */ + struct shinstance *parent; /**< The parent shell instance. */ + shpid pid; /**< The (fake) process id of this shell instance. */ + shtid tid; /**< The thread identifier of the thread for this shell. */ + shpid pgid; /**< Process group ID. */ + shfdtab fdtab; /**< The file descriptor table. */ + shsigaction_t sigactions[NSIG]; /**< The signal actions registered with this shell instance. */ + shsigset_t sigmask; /**< Our signal mask. */ + char **shenviron; /**< The environment vector. */ + int linked; /**< Set if we're still linked. */ + unsigned num_children; /**< Number of children in the array. */ + shchild *children; /**< The child array. */ +#ifndef SH_FORKED_MODE + int (*thread)(struct shinstance *, void *); /**< The thread procedure. */ + void *threadarg; /**< The thread argument. */ + struct jmploc *exitjmp; /**< Long jump target in sh_thread_wrapper for use by sh__exit. */ + shsubshellstatus *subshellstatus; /**< Pointer to the subshell status structure (NULL if root). */ +#endif + + /* alias.c */ +#define ATABSIZE 39 + struct alias *atab[ATABSIZE]; + unsigned aliases; /**< Number of active aliases. */ + + /* cd.c */ + char *curdir; /**< current working directory */ + char *prevdir; /**< previous working directory */ + char *cdcomppath; /**< (stalloc) */ + int getpwd_first; /**< static in getpwd. (initialized to 1!) */ + + /* error.h */ + struct jmploc *handler; + int exception; + int exerrno/* = 0 */; /**< Last exec error */ + int volatile suppressint; + int volatile intpending; + + /* error.c */ + char errmsg_buf[16]; /**< static in errmsg. (bss) */ + + /* eval.h */ + char *commandname; /**< currently executing command */ + int exitstatus; /**< exit status of last command */ + int back_exitstatus;/**< exit status of backquoted command */ + struct strlist *cmdenviron; /**< environment for builtin command (varlist from evalcommand()) */ + int funcnest; /**< depth of function calls */ + int evalskip; /**< set if we are skipping commands */ + int skipcount; /**< number of levels to skip */ + int loopnest; /**< current loop nesting level */ + int commandnamemalloc; /**< Set if commandname is malloc'ed (only subshells). */ + + /* expand.c */ + char *expdest; /**< output of current string (stack) */ + struct nodelist *argbackq; /**< list of back quote expressions */ + struct ifsregion ifsfirst; /**< first struct in list of ifs regions */ + struct ifsregion *ifslastp; /**< last struct in list */ + struct arglist exparg; /**< holds expanded arg list (stack) */ + char *expdir; /**< Used by expandmeta. */ + + /* exec.h */ + const char *pathopt; /**< set by padvance */ + + /* exec.c */ + struct tblentry *cmdtable[CMDTABLESIZE]; + int builtinloc/* = -1*/; /**< index in path of %builtin, or -1 */ + + /* input.h */ + int plinno/* = 1 */;/**< input line number */ + int parsenleft; /**< number of characters left in input buffer */ + char *parsenextc; /**< next character in input buffer */ + int init_editline/* = 0 */; /**< 0 == not setup, 1 == OK, -1 == failed */ + + /* input.c */ + int parselleft; /**< copy of parsefile->lleft */ + struct parsefile basepf; /**< top level input file */ + char basebuf[BUFSIZ];/**< buffer for top level input file */ + struct parsefile *parsefile/* = &basepf*/; /**< current input file */ +#ifndef SMALL + EditLine *el; /**< cookie for editline package */ +#endif + + /* jobs.h */ + shpid backgndpid/* = -1 */; /**< pid of last background process */ + int job_warning; /**< user was warned about stopped jobs */ + + /* jobs.c */ + struct job *jobtab; /**< array of jobs */ + int njobs; /**< size of array */ + int jobs_invalid; /**< set in child */ + shpid initialpgrp; /**< pgrp of shell on invocation */ + int curjob/* = -1*/;/**< current job */ + int ttyfd/* = -1*/; + int jobctl; /**< job control enabled / disabled */ + char *cmdnextc; + int cmdnleft; + + + /* mail.c */ +#define MAXMBOXES 10 + int nmboxes; /**< number of mailboxes */ + time_t mailtime[MAXMBOXES]; /**< times of mailboxes */ + + /* main.h */ + shpid rootpid; /**< pid of main shell. */ + int rootshell; /**< true if we aren't a child of the main shell. */ + struct shinstance *psh_rootshell; /**< The root shell pointer. (!rootshell) */ + + /* memalloc.h */ + char *stacknxt/* = stackbase.space*/; + int stacknleft/* = MINSIZE*/; + int sstrnleft; + int herefd/* = -1 */; + + /* memalloc.c */ + struct stack_block stackbase; + struct stack_block *stackp/* = &stackbase*/; + struct stackmark *markp; + +#ifdef KASH_SEPARATE_PARSER_ALLOCATOR + pstack_block *curpstack; /**< The pstack entry we're currently allocating from (NULL when not in parse.c). */ + pstack_block **pstack; /**< Stack of parsed stuff. */ + unsigned pstacksize; /**< Number of entries in pstack. */ + unsigned pstackalloced; /**< The allocated size of pstack. */ + pstack_block *freepstack; /**< One cached pstack entry (lots of parsecmd calls). */ +#endif + + /* myhistedit.h */ + int displayhist; +#ifndef SMALL + History *hist; + EditLine *el; +#endif + + /* output.h */ + struct output output; + struct output errout; + struct output memout; + struct output *out1; + struct output *out2; + + /* output.c */ +#define OUTBUFSIZ BUFSIZ +#define MEM_OUT -3 /**< output to dynamically allocated memory */ + + /* options.h */ + struct optent optlist[NOPTS]; + char *minusc; /**< argument to -c option */ + char *arg0; /**< $0 */ + struct shparam shellparam; /**< $@ */ + char **argptr; /**< argument list for builtin commands */ + char *optionarg; /**< set by nextopt */ + char *optptr; /**< used by nextopt */ + char **orgargv; /**< The original argument vector (for cleanup). */ + int arg0malloc; /**< Indicates whether arg0 was allocated or is part of orgargv. */ + + /* parse.h */ + int tokpushback; + int whichprompt; /**< 1 == PS1, 2 == PS2 */ + + /* parser.c */ + int noalias/* = 0*/;/**< when set, don't handle aliases */ + struct heredoc *heredoclist; /**< list of here documents to read */ + int parsebackquote; /**< nonzero if we are inside backquotes */ + int doprompt; /**< if set, prompt the user */ + int needprompt; /**< true if interactive and at start of line */ + int lasttoken; /**< last token read */ + char *wordtext; /**< text of last word returned by readtoken */ + int checkkwd; /**< 1 == check for kwds, 2 == also eat newlines */ + struct nodelist *backquotelist; + union node *redirnode; + struct heredoc *heredoc; + int quoteflag; /**< set if (part of) last token was quoted */ + int startlinno; /**< line # where last token started */ + + /* redir.c */ + struct redirtab *redirlist; + int fd0_redirected/* = 0*/; + redirexpfnames *expfnames; /**< Expanded filenames for current redirection setup. */ + + /* show.c */ + char tracebuf[1024]; + size_t tracepos; + int tracefd; + + /* trap.h */ + int pendingsigs; /**< indicates some signal received */ + + /* trap.c */ + char gotsig[NSIG]; /**< indicates specified signal received */ + char *trap[NSIG+1]; /**< trap handler commands */ + char sigmode[NSIG]; /**< current value of signal */ + + /* var.h */ + struct localvar *localvars; + struct var vatty; + struct var vifs; + struct var vmail; + struct var vmpath; + struct var vpath; +#ifdef _MSC_VER + struct var vpath2; +#endif + struct var vps1; + struct var vps2; + struct var vps4; +#ifndef SMALL + struct var vterm; + struct var vhistsize; +#endif + struct var voptind; +#ifdef PC_OS2_LIBPATHS + struct var libpath_vars[4]; +#endif +#ifdef SMALL +# define VTABSIZE 39 +#else +# define VTABSIZE 517 +#endif + struct var *vartab[VTABSIZE]; + + /* builtins.h */ + + /* bltin/test.c */ + char **t_wp; + struct t_op const *t_wp_op; +}; + +extern void sh_init_globals(void); +extern shinstance *sh_create_root_shell(char **, char **); +extern shinstance *sh_create_child_shell(shinstance *); + +/* environment & pwd.h */ +char *sh_getenv(shinstance *, const char *); +char **sh_environ(shinstance *); +const char *sh_gethomedir(shinstance *, const char *); + +/* signals */ +#define SH_SIG_UNK ((shsig_t)(intptr_t)-199) +#define SH_SIG_DFL ((shsig_t)(intptr_t)SIG_DFL) +#define SH_SIG_IGN ((shsig_t)(intptr_t)SIG_IGN) +#define SH_SIG_ERR ((shsig_t)(intptr_t)SIG_ERR) +#ifdef _MSC_VER +# define SA_RESTART 0x02 +# define SIG_BLOCK 1 +# define SIG_UNBLOCK 2 +# define SIG_SETMASK 3 + +# define SIGHUP 1 /* _SIGHUP_IGNORE */ +/*# define SIGINT 2 */ +# define SIGQUIT 3 /* _SIGQUIT_IGNORE */ +/*# define SIGILL 4 */ +/*# define SIGFPE 8 */ +/*# define SIGSEGV 11 */ +# define SIGPIPE 13 /* _SIGPIPE_IGNORE */ +/*# define SIGTERM 15 */ +# define SIGTTIN 16 /* _SIGIOINT_IGNORE */ +# define SIGTSTP 17 /* _SIGSTOP_IGNORE */ +# define SIGTTOU 18 +# define SIGCONT 20 +/*# define SIGBREAK 21 */ +/*# define SIGABRT 22 */ +const char *strsignal(int iSig); +#endif /* _MSC_VER */ +#ifndef HAVE_SYS_SIGNAME +extern const char * const sys_signame[NSIG]; +#endif + +int sh_sigaction(shinstance *, int, const struct shsigaction *, struct shsigaction *); +shsig_t sh_signal(shinstance *, int, shsig_t); +int sh_siginterrupt(shinstance *, int, int); +void sh_sigemptyset(shsigset_t *); +void sh_sigfillset(shsigset_t *); +void sh_sigaddset(shsigset_t *, int); +void sh_sigdelset(shsigset_t *, int); +int sh_sigismember(shsigset_t const *, int); +int sh_sigprocmask(shinstance *, int, shsigset_t const *, shsigset_t *); +SH_NORETURN_1 void sh_abort(shinstance *) SH_NORETURN_2; +void sh_raise_sigint(shinstance *); +int sh_kill(shinstance *, shpid, int); +int sh_killpg(shinstance *, shpid, int); + +/* times */ +#include <time.h> +#ifdef _MSC_VER + typedef struct shtms + { + clock_t tms_utime; + clock_t tms_stime; + clock_t tms_cutime; + clock_t tms_cstime; + } shtms; +#else +# include <sys/times.h> + typedef struct tms shtms; +#endif +clock_t sh_times(shinstance *, shtms *); +int sh_sysconf_clk_tck(void); + +/* wait / process */ +int sh_add_child(shinstance *psh, shpid pid, void *hChild, struct shsubshellstatus *sts); +#ifdef _MSC_VER +# include <process.h> +# define WNOHANG 1 /* Don't hang in wait. */ +# define WUNTRACED 2 /* Tell about stopped, untraced children. */ +# define WCONTINUED 4 /* Report a job control continued process. */ +# define _W_INT(w) (*(int *)&(w)) /* Convert union wait to int. */ +# define WCOREFLAG 0200 +# define _WSTATUS(x) (_W_INT(x) & 0177) +# define _WSTOPPED 0177 /* _WSTATUS if process is stopped */ +# define WIFSTOPPED(x) (_WSTATUS(x) == _WSTOPPED) +# define WSTOPSIG(x) (_W_INT(x) >> 8) +# define WIFSIGNALED(x) (_WSTATUS(x) != 0 && !WIFSTOPPED(x) && !WIFCONTINUED(x)) /* bird: made GLIBC tests happy. */ +# define WTERMSIG(x) (_WSTATUS(x)) +# define WIFEXITED(x) (_WSTATUS(x) == 0) +# define WEXITSTATUS(x) (_W_INT(x) >> 8) +# define WIFCONTINUED(x) (x == 0x13) /* 0x13 == SIGCONT */ +# define WCOREDUMP(x) (_W_INT(x) & WCOREFLAG) +# define W_EXITCODE(ret, sig) ((ret) << 8 | (sig)) +# define W_STOPCODE(sig) ((sig) << 8 | _WSTOPPED) +#else +# include <sys/wait.h> +# ifdef __HAIKU__ +# define WCOREDUMP(x) WIFCORED(x) +# endif +#endif +#ifdef SH_FORKED_MODE +shpid sh_fork(shinstance *); +#else +shpid sh_thread_start(shinstance *pshparent, shinstance *pshchild, int (*thread)(shinstance *, void *), void *arg); +#endif +shpid sh_waitpid(shinstance *, shpid, int *, int); +SH_NORETURN_1 void sh__exit(shinstance *, int) SH_NORETURN_2; +int sh_execve(shinstance *, const char *, const char * const*, const char * const *); +uid_t sh_getuid(shinstance *); +uid_t sh_geteuid(shinstance *); +gid_t sh_getgid(shinstance *); +gid_t sh_getegid(shinstance *); +shpid sh_getpid(shinstance *); +shpid sh_getpgrp(shinstance *); +shpid sh_getpgid(shinstance *, shpid); +int sh_setpgid(shinstance *, shpid, shpid); + +/* tc* */ +shpid sh_tcgetpgrp(shinstance *, int); +int sh_tcsetpgrp(shinstance *, int, shpid); + +/* sys/resource.h */ +#ifdef _MSC_VER + typedef int64_t shrlim_t; + typedef struct shrlimit + { + shrlim_t rlim_cur; + shrlim_t rlim_max; + } shrlimit; +# define RLIMIT_CPU 0 +# define RLIMIT_FSIZE 1 +# define RLIMIT_DATA 2 +# define RLIMIT_STACK 3 +# define RLIMIT_CORE 4 +# define RLIMIT_RSS 5 +# define RLIMIT_MEMLOCK 6 +# define RLIMIT_NPROC 7 +# define RLIMIT_NOFILE 8 +# define RLIMIT_SBSIZE 9 +# define RLIMIT_VMEM 10 +# define RLIM_NLIMITS 11 +# define RLIM_INFINITY (0x7fffffffffffffffLL) +#else + typedef rlim_t shrlim_t; + typedef struct rlimit shrlimit; +#endif +int sh_getrlimit(shinstance *, int, shrlimit *); +int sh_setrlimit(shinstance *, int, const shrlimit *); + +/* string.h */ +const char *sh_strerror(shinstance *, int); + +#ifdef DEBUG +# define TRACE2(param) trace param +# define TRACE2V(param) tracev param +#else +# define TRACE2(param) do { } while (0) +# define TRACE2V(param) do { } while (0) +#endif + +#endif |