ash: preparatory work for pipefail and code shrink. -44 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
Denys Vlasenko 2009-12-04 23:02:27 +01:00
parent 7a7b034482
commit 285ad155c4

View File

@ -100,15 +100,15 @@ static const char *const optletters_optnames[] = {
"a" "allexport", "a" "allexport",
"b" "notify", "b" "notify",
"u" "nounset", "u" "nounset",
"\0" "vi" "\0" "vi",
#if DEBUG #if DEBUG
,"\0" "nolog" ,"\0" "nolog"
,"\0" "debug" ,"\0" "debug"
#endif #endif
}; };
#define optletters(n) optletters_optnames[(n)][0] #define optletters(n) optletters_optnames[n][0]
#define optnames(n) (&optletters_optnames[(n)][1]) #define optnames(n) (optletters_optnames[n] + 1)
enum { NOPTS = ARRAY_SIZE(optletters_optnames) }; enum { NOPTS = ARRAY_SIZE(optletters_optnames) };
@ -3194,8 +3194,8 @@ unaliascmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
/* ============ jobs.c */ /* ============ jobs.c */
/* Mode argument to forkshell. Don't change FORK_FG or FORK_BG. */ /* Mode argument to forkshell. Don't change FORK_FG or FORK_BG. */
#define FORK_FG 0 #define FORK_FG 0
#define FORK_BG 1 #define FORK_BG 1
#define FORK_NOJOB 2 #define FORK_NOJOB 2
/* mode flags for showjob(s) */ /* mode flags for showjob(s) */
@ -3210,9 +3210,9 @@ unaliascmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
* array of pids. * array of pids.
*/ */
struct procstat { struct procstat {
pid_t pid; /* process id */ pid_t ps_pid; /* process id */
int status; /* last process status from wait() */ int ps_status; /* last process status from wait() */
char *cmd; /* text of command being run */ char *ps_cmd; /* text of command being run */
}; };
struct job { struct job {
@ -3518,7 +3518,7 @@ getjob(const char *name, int getctl)
found = NULL; found = NULL;
while (jp) { while (jp) {
if (match(jp->ps[0].cmd, p)) { if (match(jp->ps[0].ps_cmd, p)) {
if (found) if (found)
goto err; goto err;
found = jp; found = jp;
@ -3552,8 +3552,8 @@ freejob(struct job *jp)
INT_OFF; INT_OFF;
for (i = jp->nprocs, ps = jp->ps; --i >= 0; ps++) { for (i = jp->nprocs, ps = jp->ps; --i >= 0; ps++) {
if (ps->cmd != nullstr) if (ps->ps_cmd != nullstr)
free(ps->cmd); free(ps->ps_cmd);
} }
if (jp->ps != &jp->ps0) if (jp->ps != &jp->ps0)
free(jp->ps); free(jp->ps);
@ -3655,7 +3655,7 @@ killcmd(int argc, char **argv)
do { do {
if (argv[i][0] == '%') { if (argv[i][0] == '%') {
struct job *jp = getjob(argv[i], 0); struct job *jp = getjob(argv[i], 0);
unsigned pid = jp->ps[0].pid; unsigned pid = jp->ps[0].ps_pid;
/* Enough space for ' -NNN<nul>' */ /* Enough space for ' -NNN<nul>' */
argv[i] = alloca(sizeof(int)*3 + 3); argv[i] = alloca(sizeof(int)*3 + 3);
/* kill_main has matching code to expect /* kill_main has matching code to expect
@ -3669,15 +3669,15 @@ killcmd(int argc, char **argv)
} }
static void static void
showpipe(struct job *jp, FILE *out) showpipe(struct job *jp /*, FILE *out*/)
{ {
struct procstat *sp; struct procstat *ps;
struct procstat *spend; struct procstat *psend;
spend = jp->ps + jp->nprocs; psend = jp->ps + jp->nprocs;
for (sp = jp->ps + 1; sp < spend; sp++) for (ps = jp->ps + 1; ps < psend; ps++)
fprintf(out, " | %s", sp->cmd); printf(" | %s", ps->ps_cmd);
outcslow('\n', out); outcslow('\n', stdout);
flush_stdout_stderr(); flush_stdout_stderr();
} }
@ -3694,15 +3694,15 @@ restartjob(struct job *jp, int mode)
if (jp->state == JOBDONE) if (jp->state == JOBDONE)
goto out; goto out;
jp->state = JOBRUNNING; jp->state = JOBRUNNING;
pgid = jp->ps->pid; pgid = jp->ps[0].ps_pid;
if (mode == FORK_FG) if (mode == FORK_FG)
xtcsetpgrp(ttyfd, pgid); xtcsetpgrp(ttyfd, pgid);
killpg(pgid, SIGCONT); killpg(pgid, SIGCONT);
ps = jp->ps; ps = jp->ps;
i = jp->nprocs; i = jp->nprocs;
do { do {
if (WIFSTOPPED(ps->status)) { if (WIFSTOPPED(ps->ps_status)) {
ps->status = -1; ps->ps_status = -1;
} }
ps++; ps++;
} while (--i); } while (--i);
@ -3716,22 +3716,20 @@ static int FAST_FUNC
fg_bgcmd(int argc UNUSED_PARAM, char **argv) fg_bgcmd(int argc UNUSED_PARAM, char **argv)
{ {
struct job *jp; struct job *jp;
FILE *out;
int mode; int mode;
int retval; int retval;
mode = (**argv == 'f') ? FORK_FG : FORK_BG; mode = (**argv == 'f') ? FORK_FG : FORK_BG;
nextopt(nullstr); nextopt(nullstr);
argv = argptr; argv = argptr;
out = stdout;
do { do {
jp = getjob(*argv, 1); jp = getjob(*argv, 1);
if (mode == FORK_BG) { if (mode == FORK_BG) {
set_curjob(jp, CUR_RUNNING); set_curjob(jp, CUR_RUNNING);
fprintf(out, "[%d] ", jobno(jp)); printf("[%d] ", jobno(jp));
} }
outstr(jp->ps->cmd, out); out1str(jp->ps[0].ps_cmd);
showpipe(jp, out); showpipe(jp /*, stdout*/);
retval = restartjob(jp, mode); retval = restartjob(jp, mode);
} while (*argv && *++argv); } while (*argv && *++argv);
return retval; return retval;
@ -3790,8 +3788,9 @@ dowait(int wait_flags, struct job *job)
/* Do a wait system call. If job control is compiled in, we accept /* Do a wait system call. If job control is compiled in, we accept
* stopped processes. wait_flags may have WNOHANG, preventing blocking. * stopped processes. wait_flags may have WNOHANG, preventing blocking.
* NB: _not_ safe_waitpid, we need to detect EINTR */ * NB: _not_ safe_waitpid, we need to detect EINTR */
pid = waitpid(-1, &status, if (doing_jobctl)
(doing_jobctl ? (wait_flags | WUNTRACED) : wait_flags)); wait_flags |= WUNTRACED;
pid = waitpid(-1, &status, wait_flags);
TRACE(("wait returns pid=%d, status=0x%x, errno=%d(%s)\n", TRACE(("wait returns pid=%d, status=0x%x, errno=%d(%s)\n",
pid, status, errno, strerror(errno))); pid, status, errno, strerror(errno)));
if (pid <= 0) if (pid <= 0)
@ -3800,32 +3799,32 @@ dowait(int wait_flags, struct job *job)
INT_OFF; INT_OFF;
thisjob = NULL; thisjob = NULL;
for (jp = curjob; jp; jp = jp->prev_job) { for (jp = curjob; jp; jp = jp->prev_job) {
struct procstat *sp; struct procstat *ps;
struct procstat *spend; struct procstat *psend;
if (jp->state == JOBDONE) if (jp->state == JOBDONE)
continue; continue;
state = JOBDONE; state = JOBDONE;
spend = jp->ps + jp->nprocs; ps = jp->ps;
sp = jp->ps; psend = ps + jp->nprocs;
do { do {
if (sp->pid == pid) { if (ps->ps_pid == pid) {
TRACE(("Job %d: changing status of proc %d " TRACE(("Job %d: changing status of proc %d "
"from 0x%x to 0x%x\n", "from 0x%x to 0x%x\n",
jobno(jp), pid, sp->status, status)); jobno(jp), pid, ps->ps_status, status));
sp->status = status; ps->ps_status = status;
thisjob = jp; thisjob = jp;
} }
if (sp->status == -1) if (ps->ps_status == -1)
state = JOBRUNNING; state = JOBRUNNING;
#if JOBS #if JOBS
if (state == JOBRUNNING) if (state == JOBRUNNING)
continue; continue;
if (WIFSTOPPED(sp->status)) { if (WIFSTOPPED(ps->ps_status)) {
jp->stopstatus = sp->status; jp->stopstatus = ps->ps_status;
state = JOBSTOPPED; state = JOBSTOPPED;
} }
#endif #endif
} while (++sp < spend); } while (++ps < psend);
if (thisjob) if (thisjob)
goto gotjob; goto gotjob;
} }
@ -3891,7 +3890,7 @@ showjob(FILE *out, struct job *jp, int mode)
if (mode & SHOW_ONLY_PGID) { /* jobs -p */ if (mode & SHOW_ONLY_PGID) { /* jobs -p */
/* just output process (group) id of pipeline */ /* just output process (group) id of pipeline */
fprintf(out, "%d\n", ps->pid); fprintf(out, "%d\n", ps->ps_pid);
return; return;
} }
@ -3904,7 +3903,7 @@ showjob(FILE *out, struct job *jp, int mode)
s[col - 3] = '-'; s[col - 3] = '-';
if (mode & SHOW_PIDS) if (mode & SHOW_PIDS)
col += fmtstr(s + col, 16, "%d ", ps->pid); col += fmtstr(s + col, 16, "%d ", ps->ps_pid);
psend = ps + jp->nprocs; psend = ps + jp->nprocs;
@ -3912,7 +3911,7 @@ showjob(FILE *out, struct job *jp, int mode)
strcpy(s + col, "Running"); strcpy(s + col, "Running");
col += sizeof("Running") - 1; col += sizeof("Running") - 1;
} else { } else {
int status = psend[-1].status; int status = psend[-1].ps_status;
if (jp->state == JOBSTOPPED) if (jp->state == JOBSTOPPED)
status = jp->stopstatus; status = jp->stopstatus;
col += sprint_status(s + col, status, 0); col += sprint_status(s + col, status, 0);
@ -3928,20 +3927,20 @@ showjob(FILE *out, struct job *jp, int mode)
* making it impossible to know 1st process status. * making it impossible to know 1st process status.
*/ */
goto start; goto start;
while (1) { do {
/* for each process */ /* for each process */
s[0] = '\0'; s[0] = '\0';
col = 33; col = 33;
if (mode & SHOW_PIDS) if (mode & SHOW_PIDS)
col = fmtstr(s, 48, "\n%*c%d ", indent_col, ' ', ps->pid) - 1; col = fmtstr(s, 48, "\n%*c%d ", indent_col, ' ', ps->ps_pid) - 1;
start: start:
fprintf(out, "%s%*c", s, 33 - col >= 0 ? 33 - col : 0, ' '); fprintf(out, "%s%*c%s%s",
if (ps != jp->ps) s,
fprintf(out, "| "); 33 - col >= 0 ? 33 - col : 0, ' ',
fprintf(out, "%s", ps->cmd); ps == jp->ps ? "" : "| ",
if (++ps == psend) ps->ps_cmd
break; );
} } while (++ps != psend);
outcslow('\n', out); outcslow('\n', out);
jp->changed = 0; jp->changed = 0;
@ -3992,8 +3991,9 @@ jobscmd(int argc UNUSED_PARAM, char **argv)
do do
showjob(stdout, getjob(*argv, 0), mode); showjob(stdout, getjob(*argv, 0), mode);
while (*++argv); while (*++argv);
} else } else {
showjobs(stdout, mode); showjobs(stdout, mode);
}
return 0; return 0;
} }
@ -4005,7 +4005,7 @@ getstatus(struct job *job)
int status; int status;
int retval; int retval;
status = job->ps[job->nprocs - 1].status; status = job->ps[job->nprocs - 1].ps_status;
retval = WEXITSTATUS(status); retval = WEXITSTATUS(status);
if (!WIFEXITED(status)) { if (!WIFEXITED(status)) {
#if JOBS #if JOBS
@ -4072,7 +4072,7 @@ waitcmd(int argc UNUSED_PARAM, char **argv)
while (1) { while (1) {
if (!job) if (!job)
goto repeat; goto repeat;
if (job->ps[job->nprocs - 1].pid == pid) if (job->ps[job->nprocs - 1].ps_pid == pid)
break; break;
job = job->prev_job; job = job->prev_job;
} }
@ -4576,7 +4576,7 @@ forkchild(struct job *jp, union node *n, int mode)
if (jp->nprocs == 0) if (jp->nprocs == 0)
pgrp = getpid(); pgrp = getpid();
else else
pgrp = jp->ps[0].pid; pgrp = jp->ps[0].ps_pid;
/* this can fail because we are doing it in the parent also */ /* this can fail because we are doing it in the parent also */
setpgid(0, pgrp); setpgid(0, pgrp);
if (mode == FORK_FG) if (mode == FORK_FG)
@ -4648,7 +4648,7 @@ forkparent(struct job *jp, union node *n, int mode, pid_t pid)
if (jp->nprocs == 0) if (jp->nprocs == 0)
pgrp = pid; pgrp = pid;
else else
pgrp = jp->ps[0].pid; pgrp = jp->ps[0].ps_pid;
/* This can fail because we are doing it in the child also */ /* This can fail because we are doing it in the child also */
setpgid(pid, pgrp); setpgid(pid, pgrp);
} }
@ -4659,12 +4659,12 @@ forkparent(struct job *jp, union node *n, int mode, pid_t pid)
} }
if (jp) { if (jp) {
struct procstat *ps = &jp->ps[jp->nprocs++]; struct procstat *ps = &jp->ps[jp->nprocs++];
ps->pid = pid; ps->ps_pid = pid;
ps->status = -1; ps->ps_status = -1;
ps->cmd = nullstr; ps->ps_cmd = nullstr;
#if JOBS #if JOBS
if (doing_jobctl && n) if (doing_jobctl && n)
ps->cmd = commandtext(n); ps->ps_cmd = commandtext(n);
#endif #endif
} }
} }
@ -7683,7 +7683,7 @@ describe_command(char *command, int describe_command_verbose)
return 127; return 127;
} }
out: out:
outstr("\n", stdout); out1str("\n");
return 0; return 0;
} }
@ -11852,8 +11852,9 @@ evalcmd(int argc UNUSED_PARAM, char **argv)
} }
/* /*
* Read and execute commands. "Top" is nonzero for the top level command * Read and execute commands.
* loop; it turns on prompting if the shell is interactive. * "Top" is nonzero for the top level command loop;
* it turns on prompting if the shell is interactive.
*/ */
static int static int
cmdloop(int top) cmdloop(int top)