📄 ash.c
字号:
return (i);}static struct alias **hashalias(p) const char *p; { unsigned int hashval; hashval = *p << 4; while (*p) hashval+= *p++; return &atab[hashval % ATABSIZE];}static struct alias *freealias(struct alias *ap) { struct alias *next; if (ap->flag & ALIASINUSE) { ap->flag |= ALIASDEAD; return ap; } next = ap->next; ckfree(ap->name); ckfree(ap->val); ckfree(ap); return next;}static struct alias **__lookupalias(const char *name) { struct alias **app = hashalias(name); for (; *app; app = &(*app)->next) { if (equal(name, (*app)->name)) { break; } } return app;}#endif#ifdef ASH_MATH_SUPPORT/* The generated file arith.c has been replaced with a custom hand * written implementation written by Aaron Lehmann <aaronl@vitelus.com>. * This is now part of libbb, so that it can be used by all the shells * in busybox. */#define ARITH_NUM 257#define ARITH_LPAREN 258#define ARITH_RPAREN 259#define ARITH_OR 260#define ARITH_AND 261#define ARITH_BOR 262#define ARITH_BXOR 263#define ARITH_BAND 264#define ARITH_EQ 265#define ARITH_NE 266#define ARITH_LT 267#define ARITH_GT 268#define ARITH_GE 269#define ARITH_LE 270#define ARITH_LSHIFT 271#define ARITH_RSHIFT 272#define ARITH_ADD 273#define ARITH_SUB 274#define ARITH_MUL 275#define ARITH_DIV 276#define ARITH_REM 277#define ARITH_UNARYMINUS 278#define ARITH_UNARYPLUS 279#define ARITH_NOT 280#define ARITH_BNOT 281static void expari (int);#endifstatic char *trap[NSIG]; /* trap handler commands */static char sigmode[NSIG - 1]; /* current value of signal */static char gotsig[NSIG - 1]; /* indicates specified signal received */static int pendingsigs; /* indicates some signal received *//* * This file was generated by the mkbuiltins program. */#ifdef JOBSstatic int bgcmd (int, char **);static int fgcmd (int, char **);static int killcmd (int, char **);#endifstatic int bltincmd (int, char **);static int cdcmd (int, char **);static int breakcmd (int, char **);#ifdef ASH_CMDCMDstatic int commandcmd (int, char **);#endifstatic int dotcmd (int, char **);static int evalcmd (int, char **);static int execcmd (int, char **);static int exitcmd (int, char **);static int exportcmd (int, char **);static int histcmd (int, char **);static int hashcmd (int, char **);static int helpcmd (int, char **);static int jobscmd (int, char **);static int localcmd (int, char **);#ifndef BB_PWDstatic int pwdcmd (int, char **);#endifstatic int readcmd (int, char **);static int returncmd (int, char **);static int setcmd (int, char **);static int setvarcmd (int, char **);static int shiftcmd (int, char **);static int trapcmd (int, char **);static int umaskcmd (int, char **);#ifdef ASH_ALIASstatic int aliascmd (int, char **);static int unaliascmd (int, char **);#endifstatic int unsetcmd (int, char **);static int waitcmd (int, char **);static int ulimitcmd (int, char **);static int timescmd (int, char **);#ifdef ASH_MATH_SUPPORTstatic int letcmd (int, char **);#endifstatic int typecmd (int, char **);#ifdef ASH_GETOPTSstatic int getoptscmd (int, char **);#endif#ifndef BB_TRUE_FALSEstatic int true_main (int, char **);static int false_main (int, char **);#endifstatic void setpwd (const char *, int);#define BUILTIN_NOSPEC "0"#define BUILTIN_SPECIAL "1"#define BUILTIN_REGULAR "2"#define BUILTIN_ASSIGN "4"#define BUILTIN_SPEC_ASSG "5"#define BUILTIN_REG_ASSG "6"#define IS_BUILTIN_SPECIAL(builtincmd) ((builtincmd)->name[0] & 1)#define IS_BUILTIN_REGULAR(builtincmd) ((builtincmd)->name[0] & 2)#define IS_BUILTIN_ASSIGN(builtincmd) ((builtincmd)->name[0] & 4)struct builtincmd { const char *name; int (*const builtinfunc) (int, char **); //unsigned flags;};/* It is CRUCIAL that this listing be kept in ascii order, otherwise * the binary search in find_builtin() will stop working. If you value * your kneecaps, you'll be sure to *make sure* that any changes made * to this array result in the listing remaining in ascii order. You * have been warned. */static const struct builtincmd builtincmds[] = { { BUILTIN_SPECIAL ".", dotcmd }, /* first, see declare DOTCMD */ { BUILTIN_SPECIAL ":", true_main },#ifdef ASH_ALIAS { BUILTIN_REG_ASSG "alias", aliascmd },#endif#ifdef JOBS { BUILTIN_REGULAR "bg", bgcmd },#endif { BUILTIN_SPECIAL "break", breakcmd }, { BUILTIN_SPECIAL "builtin", bltincmd }, { BUILTIN_REGULAR "cd", cdcmd }, { BUILTIN_NOSPEC "chdir", cdcmd },#ifdef ASH_CMDCMD { BUILTIN_REGULAR "command", commandcmd },#endif { BUILTIN_SPECIAL "continue", breakcmd }, { BUILTIN_SPECIAL "eval", evalcmd }, { BUILTIN_SPECIAL "exec", execcmd }, { BUILTIN_SPECIAL "exit", exitcmd }, { BUILTIN_SPEC_ASSG "export", exportcmd }, { BUILTIN_REGULAR "false", false_main }, { BUILTIN_REGULAR "fc", histcmd },#ifdef JOBS { BUILTIN_REGULAR "fg", fgcmd },#endif#ifdef ASH_GETOPTS { BUILTIN_REGULAR "getopts", getoptscmd },#endif { BUILTIN_NOSPEC "hash", hashcmd }, { BUILTIN_NOSPEC "help", helpcmd }, { BUILTIN_REGULAR "jobs", jobscmd },#ifdef JOBS { BUILTIN_REGULAR "kill", killcmd },#endif#ifdef ASH_MATH_SUPPORT { BUILTIN_REGULAR "let", letcmd },#endif { BUILTIN_ASSIGN "local", localcmd },#ifndef BB_PWD { BUILTIN_NOSPEC "pwd", pwdcmd },#endif { BUILTIN_REGULAR "read", readcmd }, { BUILTIN_SPEC_ASSG "readonly", exportcmd }, { BUILTIN_SPECIAL "return", returncmd }, { BUILTIN_SPECIAL "set", setcmd }, { BUILTIN_NOSPEC "setvar", setvarcmd }, { BUILTIN_SPECIAL "shift", shiftcmd }, { BUILTIN_SPECIAL "times", timescmd }, { BUILTIN_SPECIAL "trap", trapcmd }, { BUILTIN_REGULAR "true", true_main }, { BUILTIN_NOSPEC "type", typecmd }, { BUILTIN_NOSPEC "ulimit", ulimitcmd }, { BUILTIN_REGULAR "umask", umaskcmd },#ifdef ASH_ALIAS { BUILTIN_REGULAR "unalias", unaliascmd },#endif { BUILTIN_SPECIAL "unset", unsetcmd }, { BUILTIN_REGULAR "wait", waitcmd },};#define NUMBUILTINS (sizeof (builtincmds) / sizeof (struct builtincmd) )static const struct builtincmd *DOTCMD = &builtincmds[0];static struct builtincmd *BLTINCMD;static struct builtincmd *EXECCMD;static struct builtincmd *EVALCMD;/* states */#define JOBSTOPPED 1 /* all procs are stopped */#define JOBDONE 2 /* all procs are completed *//* * 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; /* status flags (defined above) */ char *cmd; /* text of command being run */};static int job_warning; /* user was warned about stopped jobs */#ifdef JOBSstatic void setjobctl(int enable);#else#define setjobctl(on) /* do nothing */#endifstruct job { struct procstat ps0; /* status of process */ struct procstat *ps; /* status or processes when more than one */ short nprocs; /* number of processes */ short pgrp; /* process group of this job */ char state; /* true if job is finished */ char used; /* true if this entry is in used */ char changed; /* true if status has changed */#ifdef JOBS char jobctl; /* job running under job control */#endif};static struct job *jobtab; /* array of jobs */static int njobs; /* size of array */static int backgndpid = -1; /* pid of last background process */#ifdef JOBSstatic int initialpgrp; /* pgrp of shell on invocation */static int curjob; /* current job */static int jobctl;#endifstatic int intreceived;static struct job *makejob (const union node *, int);static int forkshell (struct job *, const union node *, int);static int waitforjob (struct job *);static int docd (char *, int);static char *getcomponent (void);static void updatepwd (const char *);static void getpwd (void);static char *padvance (const char **, const char *);static char nullstr[1]; /* zero length string */static char *curdir = nullstr; /* current working directory */static char *cdcomppath;static intcdcmd(argc, argv) int argc; char **argv;{ const char *dest; const char *path; char *p; struct stat statb; int print = 0; nextopt(nullstr); if ((dest = *argptr) == NULL && (dest = bltinlookup("HOME")) == NULL) error("HOME not set"); if (*dest == '\0') dest = "."; if (dest[0] == '-' && dest[1] == '\0') { dest = bltinlookup("OLDPWD"); if (!dest || !*dest) { dest = curdir; } print = 1; if (dest) print = 1; else dest = "."; } if (*dest == '/' || (path = bltinlookup("CDPATH")) == NULL) path = nullstr; while ((p = padvance(&path, dest)) != NULL) { if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) { if (!print) { /* * XXX - rethink */ if (p[0] == '.' && p[1] == '/' && p[2] != '\0') p += 2; print = strcmp(p, dest); } if (docd(p, print) >= 0) return 0; } } error("can't cd to %s", dest); /* NOTREACHED */}/* * Actually do the chdir. In an interactive shell, print the * directory name if "print" is nonzero. */static intdocd(dest, print) char *dest; int print;{ char *p; char *q; char *component; struct stat statb; int first; int badstat; TRACE(("docd(\"%s\", %d) called\n", dest, print)); /* * Check each component of the path. If we find a symlink or * something we can't stat, clear curdir to force a getcwd() * next time we get the value of the current directory. */ badstat = 0; cdcomppath = sstrdup(dest); STARTSTACKSTR(p); if (*dest == '/') { STPUTC('/', p); cdcomppath++; } first = 1; while ((q = getcomponent()) != NULL) { if (q[0] == '\0' || (q[0] == '.' && q[1] == '\0')) continue; if (! first) STPUTC('/', p); first = 0; component = q; while (*q) STPUTC(*q++, p); if (equal(component, "..")) continue; STACKSTRNUL(p); if ((lstat(stackblock(), &statb) < 0) || (S_ISLNK(statb.st_mode))) { /* print = 1; */ badstat = 1; break; } } INTOFF; if (chdir(dest) < 0) { INTON; return -1; } updatepwd(badstat ? NULL : dest); INTON; if (print && iflag) printf(snlfmt, curdir); return 0;}/* * Get the next component of the path name pointed to by cdcomppath. * This routine overwrites the string pointed to by cdcomppath. */static char *getcomponent() { char *p; char *start; if ((p = cdcomppath) == NULL) return NULL; start = cdcomppath; while (*p != '/' && *p != '\0') p++; if (*p == '\0') { cdcomppath = NULL; } else { *p++ = '\0'; cdcomppath = p; } return start;}/* * Update curdir (the name of the current directory) in response to a * cd command. We also call hashcd to let the routines in exec.c know * that the current directory has changed. */static void hashcd (void);static voidupdatepwd(const char *dir){ char *new; char *p; size_t len; hashcd(); /* update command hash table */ /* * If our argument is NULL, we don't know the current directory * any more because we traversed a symbolic link or something * we couldn't stat(). */ if (dir == NULL || curdir == nullstr) { setpwd(0, 1); return; } len = strlen(dir); cdcomppath = sstrdup(dir); STARTSTACKSTR(new); if (*dir != '/') { p = curdir; while (*p) STPUTC(*p++, new); if (p[-1] == '/') STUNPUTC(new); } while ((p = getcomponent()) != NULL) { if (equal(p, "..")) { while (new > stackblock() && (STUNPUTC(new), *new) != '/'); } else if (*p != '\0' && ! equal(p, ".")) { STPUTC('/', new); while (*p) STPUTC(*p++, new); } } if (new == stackblock()) STPUTC('/', new); STACKSTRNUL(new); setpwd(stackblock(), 1);}#ifndef BB_PWDstatic intpwdcmd(argc, argv) int argc; char **argv;{ printf(snlfmt, curdir); return 0;}#endif/* * Find out what the current directory is. If we already know the current * directory, this routine returns immediately.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -