📄 ash.c
字号:
#ifdef CONFIG_ASH_CMDCMD { BUILTIN_REGULAR "command", commandcmd },#endif { BUILTIN_SPEC_REG "continue", breakcmd }, { BUILTIN_SPEC_REG "eval", evalcmd }, { BUILTIN_SPEC_REG "exec", execcmd }, { BUILTIN_SPEC_REG "exit", exitcmd }, { BUILTIN_SPEC_REG_ASSG "export", exportcmd }, { BUILTIN_REGULAR "false", falsecmd },#ifdef JOBS { BUILTIN_REGULAR "fg", fgcmd },#endif#ifdef CONFIG_ASH_GETOPTS { BUILTIN_REGULAR "getopts", getoptscmd },#endif { BUILTIN_NOSPEC "hash", hashcmd },#ifndef CONFIG_FEATURE_SH_EXTRA_QUIET { BUILTIN_NOSPEC "help", helpcmd },#endif#ifdef JOBS { BUILTIN_REGULAR "jobs", jobscmd }, { BUILTIN_REGULAR "kill", killcmd },#endif#ifdef CONFIG_ASH_MATH_SUPPORT { BUILTIN_NOSPEC "let", letcmd },#endif { BUILTIN_ASSIGN "local", localcmd }, { BUILTIN_NOSPEC "pwd", pwdcmd }, { BUILTIN_REGULAR "read", readcmd }, { BUILTIN_SPEC_REG_ASSG "readonly", exportcmd }, { BUILTIN_SPEC_REG "return", returncmd }, { BUILTIN_SPEC_REG "set", setcmd }, { BUILTIN_SPEC_REG "shift", shiftcmd }, { BUILTIN_SPEC_REG "times", timescmd }, { BUILTIN_SPEC_REG "trap", trapcmd }, { BUILTIN_REGULAR "true", truecmd }, { BUILTIN_NOSPEC "type", typecmd }, { BUILTIN_NOSPEC "ulimit", ulimitcmd }, { BUILTIN_REGULAR "umask", umaskcmd },#ifdef CONFIG_ASH_ALIAS { BUILTIN_REGULAR "unalias", unaliascmd },#endif { BUILTIN_SPEC_REG "unset", unsetcmd }, { BUILTIN_REGULAR "wait", waitcmd },};#define NUMBUILTINS (sizeof (builtincmd) / sizeof (struct builtincmd) )struct cmdentry { int cmdtype; union param { int index; const struct builtincmd *cmd; struct funcnode *func; } u;};/* action to find_command() */#define DO_ERR 0x01 /* prints errors */#define DO_ABS 0x02 /* checks absolute paths */#define DO_NOFUNC 0x04 /* don't return shell functions, for command */#define DO_ALTPATH 0x08 /* using alternate path */#define DO_ALTBLTIN 0x20 /* %builtin in alt. path */static const char *pathopt; /* set by padvance */static void shellexec(char **, const char *, int) __attribute__((__noreturn__));static char *padvance(const char **, const char *);static void find_command(char *, struct cmdentry *, int, const char *);static struct builtincmd *find_builtin(const char *);static void hashcd(void);static void changepath(const char *);static void defun(char *, union node *);static void unsetfunc(const char *);#ifdef CONFIG_ASH_MATH_SUPPORTstatic long dash_arith(const char *);#endif#ifdef CONFIG_ASH_RANDOM_SUPPORTstatic unsigned long rseed;static void change_random(const char *);# ifndef DYNAMIC_VAR# define DYNAMIC_VAR# endif#endif/* $NetBSD: init.h,v 1.9 2002/11/24 22:35:40 christos Exp $ */static void reset(void);/* $NetBSD: var.h,v 1.21 2003/01/22 20:36:04 dsl Exp $ *//* * Shell variables. *//* flags */#define VEXPORT 0x01 /* variable is exported */#define VREADONLY 0x02 /* variable cannot be modified */#define VSTRFIXED 0x04 /* variable struct is statically allocated */#define VTEXTFIXED 0x08 /* text is statically allocated */#define VSTACK 0x10 /* text is allocated on the stack */#define VUNSET 0x20 /* the variable is not set */#define VNOFUNC 0x40 /* don't call the callback function */#define VNOSET 0x80 /* do not set variable - just readonly test */#define VNOSAVE 0x100 /* when text is on the heap before setvareq */#ifdef DYNAMIC_VAR# define VDYNAMIC 0x200 /* dynamic variable */# else# define VDYNAMIC 0#endifstruct var { struct var *next; /* next entry in hash list */ int flags; /* flags are defined above */ const char *text; /* name=value */ void (*func)(const char *); /* function to be called when */ /* the variable gets set/unset */};struct localvar { struct localvar *next; /* next local variable in list */ struct var *vp; /* the variable that was made local */ int flags; /* saved flags */ const char *text; /* saved text */};static struct localvar *localvars;/* * Shell variables. */#ifdef CONFIG_ASH_GETOPTSstatic void getoptsreset(const char *);#endif#ifdef CONFIG_LOCALE_SUPPORT#include <locale.h>static void change_lc_all(const char *value);static void change_lc_ctype(const char *value);#endif#define VTABSIZE 39static const char defpathvar[] = "PATH=/usr/local/bin:/usr/bin:/sbin:/bin";#ifdef IFS_BROKENstatic const char defifsvar[] = "IFS= \t\n";#define defifs (defifsvar + 4)#elsestatic const char defifs[] = " \t\n";#endifstatic struct var varinit[] = {#ifdef IFS_BROKEN { 0, VSTRFIXED|VTEXTFIXED, defifsvar, 0 },#else { 0, VSTRFIXED|VTEXTFIXED|VUNSET, "IFS\0", 0 },#endif#ifdef CONFIG_ASH_MAIL { 0, VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL\0", changemail }, { 0, VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH\0", changemail },#endif { 0, VSTRFIXED|VTEXTFIXED, defpathvar, changepath }, { 0, VSTRFIXED|VTEXTFIXED, "PS1=$ ", 0 }, { 0, VSTRFIXED|VTEXTFIXED, "PS2=> ", 0 }, { 0, VSTRFIXED|VTEXTFIXED, "PS4=+ ", 0 },#ifdef CONFIG_ASH_GETOPTS { 0, VSTRFIXED|VTEXTFIXED, "OPTIND=1", getoptsreset },#endif#ifdef CONFIG_ASH_RANDOM_SUPPORT {0, VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM\0", change_random },#endif#ifdef CONFIG_LOCALE_SUPPORT {0, VSTRFIXED | VTEXTFIXED | VUNSET, "LC_ALL\0", change_lc_all }, {0, VSTRFIXED | VTEXTFIXED | VUNSET, "LC_CTYPE\0", change_lc_ctype },#endif#ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY {0, VSTRFIXED | VTEXTFIXED | VUNSET, "HISTFILE\0", NULL },#endif};#define vifs varinit[0]#ifdef CONFIG_ASH_MAIL#define vmail (&vifs)[1]#define vmpath (&vmail)[1]#else#define vmpath vifs#endif#define vpath (&vmpath)[1]#define vps1 (&vpath)[1]#define vps2 (&vps1)[1]#define vps4 (&vps2)[1]#define voptind (&vps4)[1]#ifdef CONFIG_ASH_GETOPTS#define vrandom (&voptind)[1]#else#define vrandom (&vps4)[1]#endif#define defpath (defpathvar + 5)/* * The following macros access the values of the above variables. * They have to skip over the name. They return the null string * for unset variables. */#define ifsval() (vifs.text + 4)#define ifsset() ((vifs.flags & VUNSET) == 0)#define mailval() (vmail.text + 5)#define mpathval() (vmpath.text + 9)#define pathval() (vpath.text + 5)#define ps1val() (vps1.text + 4)#define ps2val() (vps2.text + 4)#define ps4val() (vps4.text + 4)#define optindval() (voptind.text + 7)#define mpathset() ((vmpath.flags & VUNSET) == 0)static void setvar(const char *, const char *, int);static void setvareq(char *, int);static void listsetvar(struct strlist *, int);static char *lookupvar(const char *);static char *bltinlookup(const char *);static char **listvars(int, int, char ***);#define environment() listvars(VEXPORT, VUNSET, 0)static int showvars(const char *, int, int);static void poplocalvars(void);static int unsetvar(const char *);#ifdef CONFIG_ASH_GETOPTSstatic int setvarsafe(const char *, const char *, int);#endifstatic int varcmp(const char *, const char *);static struct var **hashvar(const char *);static inline int varequal(const char *a, const char *b) { return !varcmp(a, b);}static int loopnest; /* current loop nesting level *//* * The parsefile structure pointed to by the global variable parsefile * contains information about the current file being read. */struct redirtab { struct redirtab *next; int renamed[10]; int nullredirs;};static struct redirtab *redirlist;static int nullredirs;extern char **environ;/* $NetBSD: output.h,v 1.16 2002/11/24 22:35:42 christos Exp $ */static void outstr(const char *, FILE *);static void outcslow(int, FILE *);static void flushall(void);static void flusherr(void);static int out1fmt(const char *, ...) __attribute__((__format__(__printf__,1,2)));static int fmtstr(char *, size_t, const char *, ...) __attribute__((__format__(__printf__,3,4)));static int preverrout_fd; /* save fd2 before print debug if xflag is set. */static void out1str(const char *p){ outstr(p, stdout);}static void out2str(const char *p){ outstr(p, stderr); flusherr();}/* * Initialization code. *//* * This routine initializes the builtin variables. */static inline voidinitvar(void){ struct var *vp; struct var *end; struct var **vpp; /* * PS1 depends on uid */#if defined(CONFIG_FEATURE_COMMAND_EDITING) && defined(CONFIG_FEATURE_SH_FANCY_PROMPT) vps1.text = "PS1=\\w \\$ ";#else if (!geteuid()) vps1.text = "PS1=# ";#endif vp = varinit; end = vp + sizeof(varinit) / sizeof(varinit[0]); do { vpp = hashvar(vp->text); vp->next = *vpp; *vpp = vp; } while (++vp < end);}static inline voidinit(void){ /* from input.c: */ { basepf.nextc = basepf.buf = basebuf; } /* from trap.c: */ { signal(SIGCHLD, SIG_DFL); } /* from var.c: */ { char **envp; char ppid[32]; initvar(); for (envp = environ ; *envp ; envp++) { if (strchr(*envp, '=')) { setvareq(*envp, VEXPORT|VTEXTFIXED); } } snprintf(ppid, sizeof(ppid), "%d", (int) getppid()); setvar("PPID", ppid, 0); setpwd(0, 0); }}/* PEOF (the end of file marker) *//* * The input line number. Input.c just defines this variable, and saves * and restores it when files are pushed and popped. The user of this * package must set its value. */static int pgetc(void);static int pgetc2(void);static int preadbuffer(void);static void pungetc(void);static void pushstring(char *, void *);static void popstring(void);static void setinputfile(const char *, int);static void setinputfd(int, int);static void setinputstring(char *);static void popfile(void);static void popallfiles(void);static void closescript(void);/* $NetBSD: jobs.h,v 1.17 2003/01/22 20:36:04 dsl Exp $ *//* Mode argument to forkshell. Don't change FORK_FG or FORK_BG. */#define FORK_FG 0#define FORK_BG 1#define FORK_NOJOB 2/* mode flags for showjob(s) */#define SHOW_PGID 0x01 /* only show pgid - for jobs -p */#define SHOW_PID 0x04 /* include process pid */#define SHOW_CHANGED 0x08 /* only jobs whose state has changed *//* * A job structure contains information about a job. A job is either a * single process or a set of processes contained in a pipeline. In the * latter case, pidlist will be non-NULL, and will point to a -1 terminated * array of pids. */struct procstat { pid_t pid; /* process id */ int status; /* last process status from wait() */ char *cmd; /* text of command being run */};struct job { struct procstat ps0; /* status of process */ struct procstat *ps; /* status or processes when more than one */#if JOBS int stopstatus; /* status of a stopped job */#endif uint32_t nprocs: 16, /* number of processes */ state: 8,#define JOBRUNNING 0 /* at least one proc running */#define JOBSTOPPED 1 /* all procs are stopped */#define JOBDONE 2 /* all procs are completed */#if JOBS sigint: 1, /* job was killed by SIGINT */ jobctl: 1, /* job running under job control */#endif waited: 1, /* true if this entry has been waited for */ used: 1, /* true if this entry is in used */ changed: 1; /* true if status has changed */ struct job *prev_job; /* previous job */};static pid_t backgndpid; /* pid of last background process */static int job_warning; /* user was warned about stopped jobs */#if JOBSstatic int jobctl; /* true if doing job control */#endifstatic struct job *makejob(union node *, int);static int forkshell(struct job *, union node *, int);static int waitforjob(struct job *);static int stoppedjobs(void);#if ! JOBS#define setjobctl(on) /* do nothing */#elsestatic void setjobctl(int);static void showjobs(FILE *, int);#endif/* $NetBSD: main.h,v 1.9 2002/11/24 22:35:41 christos Exp $ *//* pid of main shell */static int rootpid;/* true if we aren't a child of the main shell */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -