aboutsummaryrefslogtreecommitdiff
path: root/shell
diff options
context:
space:
mode:
authorvda <vda@69ca8d6d-28ef-0310-b511-8ec308f3f277>2007-02-23 21:10:06 +0000
committervda <vda@69ca8d6d-28ef-0310-b511-8ec308f3f277>2007-02-23 21:10:06 +0000
commit90ca2c0df223dace62cb3b2b4fa33538faa915f2 (patch)
treea686bc556a68108c4c4638f5c9de8bc41abe31ab /shell
parent92cc1717a9e2a69b24ba4ff44f1fce702d9edf88 (diff)
downloadbusybox-w32-90ca2c0df223dace62cb3b2b4fa33538faa915f2.tar.gz
busybox-w32-90ca2c0df223dace62cb3b2b4fa33538faa915f2.tar.bz2
busybox-w32-90ca2c0df223dace62cb3b2b4fa33538faa915f2.zip
ash: cleanup part 2.4
git-svn-id: svn://busybox.net/trunk/busybox@17966 69ca8d6d-28ef-0310-b511-8ec308f3f277
Diffstat (limited to 'shell')
-rw-r--r--shell/ash.c3089
1 files changed, 1541 insertions, 1548 deletions
diff --git a/shell/ash.c b/shell/ash.c
index e3a43979a..869ed12fd 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -1583,8 +1583,18 @@ struct localvar {
1583 1583
1584/* Forward decls for varinit[] */ 1584/* Forward decls for varinit[] */
1585#if ENABLE_LOCALE_SUPPORT 1585#if ENABLE_LOCALE_SUPPORT
1586static void change_lc_all(const char *value); 1586static void
1587static void change_lc_ctype(const char *value); 1587change_lc_all(const char *value)
1588{
1589 if (value && *value != '\0')
1590 setlocale(LC_ALL, value);
1591}
1592static void
1593change_lc_ctype(const char *value)
1594{
1595 if (value && *value != '\0')
1596 setlocale(LC_CTYPE, value);
1597}
1588#endif 1598#endif
1589#if ENABLE_ASH_MAIL 1599#if ENABLE_ASH_MAIL
1590static void chkmail(void); 1600static void chkmail(void);
@@ -2863,72 +2873,6 @@ static unsigned long rseed;
2863#endif 2873#endif
2864 2874
2865 2875
2866/* jobs.h */
2867
2868/* Mode argument to forkshell. Don't change FORK_FG or FORK_BG. */
2869#define FORK_FG 0
2870#define FORK_BG 1
2871#define FORK_NOJOB 2
2872
2873/* mode flags for showjob(s) */
2874#define SHOW_PGID 0x01 /* only show pgid - for jobs -p */
2875#define SHOW_PID 0x04 /* include process pid */
2876#define SHOW_CHANGED 0x08 /* only jobs whose state has changed */
2877
2878
2879/*
2880 * A job structure contains information about a job. A job is either a
2881 * single process or a set of processes contained in a pipeline. In the
2882 * latter case, pidlist will be non-NULL, and will point to a -1 terminated
2883 * array of pids.
2884 */
2885
2886struct procstat {
2887 pid_t pid; /* process id */
2888 int status; /* last process status from wait() */
2889 char *cmd; /* text of command being run */
2890};
2891
2892struct job {
2893 struct procstat ps0; /* status of process */
2894 struct procstat *ps; /* status or processes when more than one */
2895#if JOBS
2896 int stopstatus; /* status of a stopped job */
2897#endif
2898 uint32_t
2899 nprocs: 16, /* number of processes */
2900 state: 8,
2901#define JOBRUNNING 0 /* at least one proc running */
2902#define JOBSTOPPED 1 /* all procs are stopped */
2903#define JOBDONE 2 /* all procs are completed */
2904#if JOBS
2905 sigint: 1, /* job was killed by SIGINT */
2906 jobctl: 1, /* job running under job control */
2907#endif
2908 waited: 1, /* true if this entry has been waited for */
2909 used: 1, /* true if this entry is in used */
2910 changed: 1; /* true if status has changed */
2911 struct job *prev_job; /* previous job */
2912};
2913
2914static pid_t backgndpid; /* pid of last background process */
2915static int job_warning; /* user was warned about stopped jobs */
2916#if JOBS
2917static int jobctl; /* true if doing job control */
2918#endif
2919
2920static struct job *makejob(union node *, int);
2921static int forkshell(struct job *, union node *, int);
2922static int waitforjob(struct job *);
2923
2924#if ! JOBS
2925#define setjobctl(on) /* do nothing */
2926#else
2927static void setjobctl(int);
2928static void showjobs(FILE *, int);
2929#endif
2930
2931
2932/* main.h */ 2876/* main.h */
2933 2877
2934static void readcmdfile(char *); 2878static void readcmdfile(char *);
@@ -3159,6 +3103,1535 @@ unaliascmd(int argc, char **argv)
3159#endif /* ASH_ALIAS */ 3103#endif /* ASH_ALIAS */
3160 3104
3161 3105
3106/* ============ jobs.c */
3107
3108/* Mode argument to forkshell. Don't change FORK_FG or FORK_BG. */
3109#define FORK_FG 0
3110#define FORK_BG 1
3111#define FORK_NOJOB 2
3112
3113/* mode flags for showjob(s) */
3114#define SHOW_PGID 0x01 /* only show pgid - for jobs -p */
3115#define SHOW_PID 0x04 /* include process pid */
3116#define SHOW_CHANGED 0x08 /* only jobs whose state has changed */
3117
3118
3119/*
3120 * A job structure contains information about a job. A job is either a
3121 * single process or a set of processes contained in a pipeline. In the
3122 * latter case, pidlist will be non-NULL, and will point to a -1 terminated
3123 * array of pids.
3124 */
3125
3126struct procstat {
3127 pid_t pid; /* process id */
3128 int status; /* last process status from wait() */
3129 char *cmd; /* text of command being run */
3130};
3131
3132struct job {
3133 struct procstat ps0; /* status of process */
3134 struct procstat *ps; /* status or processes when more than one */
3135#if JOBS
3136 int stopstatus; /* status of a stopped job */
3137#endif
3138 uint32_t
3139 nprocs: 16, /* number of processes */
3140 state: 8,
3141#define JOBRUNNING 0 /* at least one proc running */
3142#define JOBSTOPPED 1 /* all procs are stopped */
3143#define JOBDONE 2 /* all procs are completed */
3144#if JOBS
3145 sigint: 1, /* job was killed by SIGINT */
3146 jobctl: 1, /* job running under job control */
3147#endif
3148 waited: 1, /* true if this entry has been waited for */
3149 used: 1, /* true if this entry is in used */
3150 changed: 1; /* true if status has changed */
3151 struct job *prev_job; /* previous job */
3152};
3153
3154static pid_t backgndpid; /* pid of last background process */
3155static int job_warning; /* user was warned about stopped jobs */
3156#if JOBS
3157static int jobctl; /* true if doing job control */
3158#endif
3159
3160static struct job *makejob(union node *, int);
3161static int forkshell(struct job *, union node *, int);
3162static int waitforjob(struct job *);
3163
3164#if ! JOBS
3165#define setjobctl(on) /* do nothing */
3166#else
3167static void setjobctl(int);
3168static void showjobs(FILE *, int);
3169#endif
3170
3171/*
3172 * Set the signal handler for the specified signal. The routine figures
3173 * out what it should be set to.
3174 */
3175static void
3176setsignal(int signo)
3177{
3178 int action;
3179 char *t, tsig;
3180 struct sigaction act;
3181
3182 t = trap[signo];
3183 if (t == NULL)
3184 action = S_DFL;
3185 else if (*t != '\0')
3186 action = S_CATCH;
3187 else
3188 action = S_IGN;
3189 if (rootshell && action == S_DFL) {
3190 switch (signo) {
3191 case SIGINT:
3192 if (iflag || minusc || sflag == 0)
3193 action = S_CATCH;
3194 break;
3195 case SIGQUIT:
3196#if DEBUG
3197 if (debug)
3198 break;
3199#endif
3200 /* FALLTHROUGH */
3201 case SIGTERM:
3202 if (iflag)
3203 action = S_IGN;
3204 break;
3205#if JOBS
3206 case SIGTSTP:
3207 case SIGTTOU:
3208 if (mflag)
3209 action = S_IGN;
3210 break;
3211#endif
3212 }
3213 }
3214
3215 t = &sigmode[signo - 1];
3216 tsig = *t;
3217 if (tsig == 0) {
3218 /*
3219 * current setting unknown
3220 */
3221 if (sigaction(signo, 0, &act) == -1) {
3222 /*
3223 * Pretend it worked; maybe we should give a warning
3224 * here, but other shells don't. We don't alter
3225 * sigmode, so that we retry every time.
3226 */
3227 return;
3228 }
3229 if (act.sa_handler == SIG_IGN) {
3230 if (mflag
3231 && (signo == SIGTSTP || signo == SIGTTIN || signo == SIGTTOU)
3232 ) {
3233 tsig = S_IGN; /* don't hard ignore these */
3234 } else
3235 tsig = S_HARD_IGN;
3236 } else {
3237 tsig = S_RESET; /* force to be set */
3238 }
3239 }
3240 if (tsig == S_HARD_IGN || tsig == action)
3241 return;
3242 switch (action) {
3243 case S_CATCH:
3244 act.sa_handler = onsig;
3245 break;
3246 case S_IGN:
3247 act.sa_handler = SIG_IGN;
3248 break;
3249 default:
3250 act.sa_handler = SIG_DFL;
3251 }
3252 *t = action;
3253 act.sa_flags = 0;
3254 sigfillset(&act.sa_mask);
3255 sigaction(signo, &act, 0);
3256}
3257
3258/* mode flags for set_curjob */
3259#define CUR_DELETE 2
3260#define CUR_RUNNING 1
3261#define CUR_STOPPED 0
3262
3263/* mode flags for dowait */
3264#define DOWAIT_NORMAL 0
3265#define DOWAIT_BLOCK 1
3266
3267#if JOBS
3268/* pgrp of shell on invocation */
3269static int initialpgrp;
3270static int ttyfd = -1;
3271#endif
3272/* array of jobs */
3273static struct job *jobtab;
3274/* size of array */
3275static unsigned njobs;
3276/* current job */
3277static struct job *curjob;
3278/* number of presumed living untracked jobs */
3279static int jobless;
3280
3281static void
3282set_curjob(struct job *jp, unsigned mode)
3283{
3284 struct job *jp1;
3285 struct job **jpp, **curp;
3286
3287 /* first remove from list */
3288 jpp = curp = &curjob;
3289 do {
3290 jp1 = *jpp;
3291 if (jp1 == jp)
3292 break;
3293 jpp = &jp1->prev_job;
3294 } while (1);
3295 *jpp = jp1->prev_job;
3296
3297 /* Then re-insert in correct position */
3298 jpp = curp;
3299 switch (mode) {
3300 default:
3301#if DEBUG
3302 abort();
3303#endif
3304 case CUR_DELETE:
3305 /* job being deleted */
3306 break;
3307 case CUR_RUNNING:
3308 /* newly created job or backgrounded job,
3309 put after all stopped jobs. */
3310 do {
3311 jp1 = *jpp;
3312#if JOBS
3313 if (!jp1 || jp1->state != JOBSTOPPED)
3314#endif
3315 break;
3316 jpp = &jp1->prev_job;
3317 } while (1);
3318 /* FALLTHROUGH */
3319#if JOBS
3320 case CUR_STOPPED:
3321#endif
3322 /* newly stopped job - becomes curjob */
3323 jp->prev_job = *jpp;
3324 *jpp = jp;
3325 break;
3326 }
3327}
3328
3329#if JOBS || DEBUG
3330static int
3331jobno(const struct job *jp)
3332{
3333 return jp - jobtab + 1;
3334}
3335#endif
3336
3337/*
3338 * Convert a job name to a job structure.
3339 */
3340static struct job *
3341getjob(const char *name, int getctl)
3342{
3343 struct job *jp;
3344 struct job *found;
3345 const char *err_msg = "No such job: %s";
3346 unsigned num;
3347 int c;
3348 const char *p;
3349 char *(*match)(const char *, const char *);
3350
3351 jp = curjob;
3352 p = name;
3353 if (!p)
3354 goto currentjob;
3355
3356 if (*p != '%')
3357 goto err;
3358
3359 c = *++p;
3360 if (!c)
3361 goto currentjob;
3362
3363 if (!p[1]) {
3364 if (c == '+' || c == '%') {
3365 currentjob:
3366 err_msg = "No current job";
3367 goto check;
3368 }
3369 if (c == '-') {
3370 if (jp)
3371 jp = jp->prev_job;
3372 err_msg = "No previous job";
3373 check:
3374 if (!jp)
3375 goto err;
3376 goto gotit;
3377 }
3378 }
3379
3380 if (is_number(p)) {
3381 num = atoi(p);
3382 if (num < njobs) {
3383 jp = jobtab + num - 1;
3384 if (jp->used)
3385 goto gotit;
3386 goto err;
3387 }
3388 }
3389
3390 match = prefix;
3391 if (*p == '?') {
3392 match = strstr;
3393 p++;
3394 }
3395
3396 found = 0;
3397 while (1) {
3398 if (!jp)
3399 goto err;
3400 if (match(jp->ps[0].cmd, p)) {
3401 if (found)
3402 goto err;
3403 found = jp;
3404 err_msg = "%s: ambiguous";
3405 }
3406 jp = jp->prev_job;
3407 }
3408
3409 gotit:
3410#if JOBS
3411 err_msg = "job %s not created under job control";
3412 if (getctl && jp->jobctl == 0)
3413 goto err;
3414#endif
3415 return jp;
3416 err:
3417 ash_msg_and_raise_error(err_msg, name);
3418}
3419
3420/*
3421 * Mark a job structure as unused.
3422 */
3423static void
3424freejob(struct job *jp)
3425{
3426 struct procstat *ps;
3427 int i;
3428
3429 INT_OFF;
3430 for (i = jp->nprocs, ps = jp->ps; --i >= 0; ps++) {
3431 if (ps->cmd != nullstr)
3432 free(ps->cmd);
3433 }
3434 if (jp->ps != &jp->ps0)
3435 free(jp->ps);
3436 jp->used = 0;
3437 set_curjob(jp, CUR_DELETE);
3438 INT_ON;
3439}
3440
3441#if JOBS
3442static void
3443xtcsetpgrp(int fd, pid_t pgrp)
3444{
3445 if (tcsetpgrp(fd, pgrp))
3446 ash_msg_and_raise_error("Cannot set tty process group (%m)");
3447}
3448
3449/*
3450 * Turn job control on and off.
3451 *
3452 * Note: This code assumes that the third arg to ioctl is a character
3453 * pointer, which is true on Berkeley systems but not System V. Since
3454 * System V doesn't have job control yet, this isn't a problem now.
3455 *
3456 * Called with interrupts off.
3457 */
3458static void
3459setjobctl(int on)
3460{
3461 int fd;
3462 int pgrp;
3463
3464 if (on == jobctl || rootshell == 0)
3465 return;
3466 if (on) {
3467 int ofd;
3468 ofd = fd = open(_PATH_TTY, O_RDWR);
3469 if (fd < 0) {
3470 /* BTW, bash will try to open(ttyname(0)) if open("/dev/tty") fails.
3471 * That sometimes helps to acquire controlling tty.
3472 * Obviously, a workaround for bugs when someone
3473 * failed to provide a controlling tty to bash! :) */
3474 fd += 3;
3475 while (!isatty(fd) && --fd >= 0)
3476 ;
3477 }
3478 fd = fcntl(fd, F_DUPFD, 10);
3479 close(ofd);
3480 if (fd < 0)
3481 goto out;
3482 fcntl(fd, F_SETFD, FD_CLOEXEC);
3483 do { /* while we are in the background */
3484 pgrp = tcgetpgrp(fd);
3485 if (pgrp < 0) {
3486 out:
3487 ash_msg("can't access tty; job control turned off");
3488 mflag = on = 0;
3489 goto close;
3490 }
3491 if (pgrp == getpgrp())
3492 break;
3493 killpg(0, SIGTTIN);
3494 } while (1);
3495 initialpgrp = pgrp;
3496
3497 setsignal(SIGTSTP);
3498 setsignal(SIGTTOU);
3499 setsignal(SIGTTIN);
3500 pgrp = rootpid;
3501 setpgid(0, pgrp);
3502 xtcsetpgrp(fd, pgrp);
3503 } else {
3504 /* turning job control off */
3505 fd = ttyfd;
3506 pgrp = initialpgrp;
3507 xtcsetpgrp(fd, pgrp);
3508 setpgid(0, pgrp);
3509 setsignal(SIGTSTP);
3510 setsignal(SIGTTOU);
3511 setsignal(SIGTTIN);
3512 close:
3513 close(fd);
3514 fd = -1;
3515 }
3516 ttyfd = fd;
3517 jobctl = on;
3518}
3519
3520static int
3521killcmd(int argc, char **argv)
3522{
3523 int signo = -1;
3524 int list = 0;
3525 int i;
3526 pid_t pid;
3527 struct job *jp;
3528
3529 if (argc <= 1) {
3530 usage:
3531 ash_msg_and_raise_error(
3532"Usage: kill [-s sigspec | -signum | -sigspec] [pid | job]... or\n"
3533"kill -l [exitstatus]"
3534 );
3535 }
3536
3537 if (**++argv == '-') {
3538 signo = get_signum(*argv + 1);
3539 if (signo < 0) {
3540 int c;
3541
3542 while ((c = nextopt("ls:")) != '\0') {
3543 switch (c) {
3544 default:
3545#if DEBUG
3546 abort();
3547#endif
3548 case 'l':
3549 list = 1;
3550 break;
3551 case 's':
3552 signo = get_signum(optionarg);
3553 if (signo < 0) {
3554 ash_msg_and_raise_error(
3555 "invalid signal number or name: %s",
3556 optionarg
3557 );
3558 }
3559 break;
3560 }
3561 }
3562 argv = argptr;
3563 } else
3564 argv++;
3565 }
3566
3567 if (!list && signo < 0)
3568 signo = SIGTERM;
3569
3570 if ((signo < 0 || !*argv) ^ list) {
3571 goto usage;
3572 }
3573
3574 if (list) {
3575 const char *name;
3576
3577 if (!*argv) {
3578 for (i = 1; i < NSIG; i++) {
3579 name = get_signame(i);
3580 if (isdigit(*name))
3581 out1fmt(snlfmt, name);
3582 }
3583 return 0;
3584 }
3585 name = get_signame(signo);
3586 if (!isdigit(*name))
3587 ash_msg_and_raise_error("invalid signal number or exit status: %s", *argptr);
3588 out1fmt(snlfmt, name);
3589 return 0;
3590 }
3591
3592 i = 0;
3593 do {
3594 if (**argv == '%') {
3595 jp = getjob(*argv, 0);
3596 pid = -jp->ps[0].pid;
3597 } else {
3598 pid = **argv == '-' ?
3599 -number(*argv + 1) : number(*argv);
3600 }
3601 if (kill(pid, signo) != 0) {
3602 ash_msg("(%d) - %m", pid);
3603 i = 1;
3604 }
3605 } while (*++argv);
3606
3607 return i;
3608}
3609
3610static void
3611showpipe(struct job *jp, FILE *out)
3612{
3613 struct procstat *sp;
3614 struct procstat *spend;
3615
3616 spend = jp->ps + jp->nprocs;
3617 for (sp = jp->ps + 1; sp < spend; sp++)
3618 fprintf(out, " | %s", sp->cmd);
3619 outcslow('\n', out);
3620 flush_stdout_stderr();
3621}
3622
3623
3624static int
3625restartjob(struct job *jp, int mode)
3626{
3627 struct procstat *ps;
3628 int i;
3629 int status;
3630 pid_t pgid;
3631
3632 INT_OFF;
3633 if (jp->state == JOBDONE)
3634 goto out;
3635 jp->state = JOBRUNNING;
3636 pgid = jp->ps->pid;
3637 if (mode == FORK_FG)
3638 xtcsetpgrp(ttyfd, pgid);
3639 killpg(pgid, SIGCONT);
3640 ps = jp->ps;
3641 i = jp->nprocs;
3642 do {
3643 if (WIFSTOPPED(ps->status)) {
3644 ps->status = -1;
3645 }
3646 } while (ps++, --i);
3647 out:
3648 status = (mode == FORK_FG) ? waitforjob(jp) : 0;
3649 INT_ON;
3650 return status;
3651}
3652
3653static int
3654fg_bgcmd(int argc, char **argv)
3655{
3656 struct job *jp;
3657 FILE *out;
3658 int mode;
3659 int retval;
3660
3661 mode = (**argv == 'f') ? FORK_FG : FORK_BG;
3662 nextopt(nullstr);
3663 argv = argptr;
3664 out = stdout;
3665 do {
3666 jp = getjob(*argv, 1);
3667 if (mode == FORK_BG) {
3668 set_curjob(jp, CUR_RUNNING);
3669 fprintf(out, "[%d] ", jobno(jp));
3670 }
3671 outstr(jp->ps->cmd, out);
3672 showpipe(jp, out);
3673 retval = restartjob(jp, mode);
3674 } while (*argv && *++argv);
3675 return retval;
3676}
3677#endif
3678
3679static int
3680sprint_status(char *s, int status, int sigonly)
3681{
3682 int col;
3683 int st;
3684
3685 col = 0;
3686 if (!WIFEXITED(status)) {
3687#if JOBS
3688 if (WIFSTOPPED(status))
3689 st = WSTOPSIG(status);
3690 else
3691#endif
3692 st = WTERMSIG(status);
3693 if (sigonly) {
3694 if (st == SIGINT || st == SIGPIPE)
3695 goto out;
3696#if JOBS
3697 if (WIFSTOPPED(status))
3698 goto out;
3699#endif
3700 }
3701 st &= 0x7f;
3702 col = fmtstr(s, 32, strsignal(st));
3703 if (WCOREDUMP(status)) {
3704 col += fmtstr(s + col, 16, " (core dumped)");
3705 }
3706 } else if (!sigonly) {
3707 st = WEXITSTATUS(status);
3708 if (st)
3709 col = fmtstr(s, 16, "Done(%d)", st);
3710 else
3711 col = fmtstr(s, 16, "Done");
3712 }
3713 out:
3714 return col;
3715}
3716
3717/*
3718 * Do a wait system call. If job control is compiled in, we accept
3719 * stopped processes. If block is zero, we return a value of zero
3720 * rather than blocking.
3721 *
3722 * System V doesn't have a non-blocking wait system call. It does
3723 * have a SIGCLD signal that is sent to a process when one of it's
3724 * children dies. The obvious way to use SIGCLD would be to install
3725 * a handler for SIGCLD which simply bumped a counter when a SIGCLD
3726 * was received, and have waitproc bump another counter when it got
3727 * the status of a process. Waitproc would then know that a wait
3728 * system call would not block if the two counters were different.
3729 * This approach doesn't work because if a process has children that
3730 * have not been waited for, System V will send it a SIGCLD when it
3731 * installs a signal handler for SIGCLD. What this means is that when
3732 * a child exits, the shell will be sent SIGCLD signals continuously
3733 * until is runs out of stack space, unless it does a wait call before
3734 * restoring the signal handler. The code below takes advantage of
3735 * this (mis)feature by installing a signal handler for SIGCLD and
3736 * then checking to see whether it was called. If there are any
3737 * children to be waited for, it will be.
3738 *
3739 * If neither SYSV nor BSD is defined, we don't implement nonblocking
3740 * waits at all. In this case, the user will not be informed when
3741 * a background process until the next time she runs a real program
3742 * (as opposed to running a builtin command or just typing return),
3743 * and the jobs command may give out of date information.
3744 */
3745static int
3746waitproc(int block, int *status)
3747{
3748 int flags = 0;
3749
3750#if JOBS
3751 if (jobctl)
3752 flags |= WUNTRACED;
3753#endif
3754 if (block == 0)
3755 flags |= WNOHANG;
3756 return wait3(status, flags, (struct rusage *)NULL);
3757}
3758
3759/*
3760 * Wait for a process to terminate.
3761 */
3762static int
3763dowait(int block, struct job *job)
3764{
3765 int pid;
3766 int status;
3767 struct job *jp;
3768 struct job *thisjob;
3769 int state;
3770
3771 TRACE(("dowait(%d) called\n", block));
3772 pid = waitproc(block, &status);
3773 TRACE(("wait returns pid %d, status=%d\n", pid, status));
3774 if (pid <= 0)
3775 return pid;
3776 INT_OFF;
3777 thisjob = NULL;
3778 for (jp = curjob; jp; jp = jp->prev_job) {
3779 struct procstat *sp;
3780 struct procstat *spend;
3781 if (jp->state == JOBDONE)
3782 continue;
3783 state = JOBDONE;
3784 spend = jp->ps + jp->nprocs;
3785 sp = jp->ps;
3786 do {
3787 if (sp->pid == pid) {
3788 TRACE(("Job %d: changing status of proc %d "
3789 "from 0x%x to 0x%x\n",
3790 jobno(jp), pid, sp->status, status));
3791 sp->status = status;
3792 thisjob = jp;
3793 }
3794 if (sp->status == -1)
3795 state = JOBRUNNING;
3796#if JOBS
3797 if (state == JOBRUNNING)
3798 continue;
3799 if (WIFSTOPPED(sp->status)) {
3800 jp->stopstatus = sp->status;
3801 state = JOBSTOPPED;
3802 }
3803#endif
3804 } while (++sp < spend);
3805 if (thisjob)
3806 goto gotjob;
3807 }
3808#if JOBS
3809 if (!WIFSTOPPED(status))
3810#endif
3811
3812 jobless--;
3813 goto out;
3814
3815 gotjob:
3816 if (state != JOBRUNNING) {
3817 thisjob->changed = 1;
3818
3819 if (thisjob->state != state) {
3820 TRACE(("Job %d: changing state from %d to %d\n",
3821 jobno(thisjob), thisjob->state, state));
3822 thisjob->state = state;
3823#if JOBS
3824 if (state == JOBSTOPPED) {
3825 set_curjob(thisjob, CUR_STOPPED);
3826 }
3827#endif
3828 }
3829 }
3830
3831 out:
3832 INT_ON;
3833
3834 if (thisjob && thisjob == job) {
3835 char s[48 + 1];
3836 int len;
3837
3838 len = sprint_status(s, status, 1);
3839 if (len) {
3840 s[len] = '\n';
3841 s[len + 1] = 0;
3842 out2str(s);
3843 }
3844 }
3845 return pid;
3846}
3847
3848#if JOBS
3849static void
3850showjob(FILE *out, struct job *jp, int mode)
3851{
3852 struct procstat *ps;
3853 struct procstat *psend;
3854 int col;
3855 int indent;
3856 char s[80];
3857
3858 ps = jp->ps;
3859
3860 if (mode & SHOW_PGID) {
3861 /* just output process (group) id of pipeline */
3862 fprintf(out, "%d\n", ps->pid);
3863 return;
3864 }
3865
3866 col = fmtstr(s, 16, "[%d] ", jobno(jp));
3867 indent = col;
3868
3869 if (jp == curjob)
3870 s[col - 2] = '+';
3871 else if (curjob && jp == curjob->prev_job)
3872 s[col - 2] = '-';
3873
3874 if (mode & SHOW_PID)
3875 col += fmtstr(s + col, 16, "%d ", ps->pid);
3876
3877 psend = ps + jp->nprocs;
3878
3879 if (jp->state == JOBRUNNING) {
3880 strcpy(s + col, "Running");
3881 col += sizeof("Running") - 1;
3882 } else {
3883 int status = psend[-1].status;
3884 if (jp->state == JOBSTOPPED)
3885 status = jp->stopstatus;
3886 col += sprint_status(s + col, status, 0);
3887 }
3888
3889 goto start;
3890
3891 do {
3892 /* for each process */
3893 col = fmtstr(s, 48, " |\n%*c%d ", indent, ' ', ps->pid) - 3;
3894 start:
3895 fprintf(out, "%s%*c%s",
3896 s, 33 - col >= 0 ? 33 - col : 0, ' ', ps->cmd
3897 );
3898 if (!(mode & SHOW_PID)) {
3899 showpipe(jp, out);
3900 break;
3901 }
3902 if (++ps == psend) {
3903 outcslow('\n', out);
3904 break;
3905 }
3906 } while (1);
3907
3908 jp->changed = 0;
3909
3910 if (jp->state == JOBDONE) {
3911 TRACE(("showjob: freeing job %d\n", jobno(jp)));
3912 freejob(jp);
3913 }
3914}
3915
3916static int
3917jobscmd(int argc, char **argv)
3918{
3919 int mode, m;
3920 FILE *out;
3921
3922 mode = 0;
3923 while ((m = nextopt("lp"))) {
3924 if (m == 'l')
3925 mode = SHOW_PID;
3926 else
3927 mode = SHOW_PGID;
3928 }
3929
3930 out = stdout;
3931 argv = argptr;
3932 if (*argv) {
3933 do
3934 showjob(out, getjob(*argv,0), mode);
3935 while (*++argv);
3936 } else
3937 showjobs(out, mode);
3938
3939 return 0;
3940}
3941
3942/*
3943 * Print a list of jobs. If "change" is nonzero, only print jobs whose
3944 * statuses have changed since the last call to showjobs.
3945 */
3946static void
3947showjobs(FILE *out, int mode)
3948{
3949 struct job *jp;
3950
3951 TRACE(("showjobs(%x) called\n", mode));
3952
3953 /* If not even one one job changed, there is nothing to do */
3954 while (dowait(DOWAIT_NORMAL, NULL) > 0)
3955 continue;
3956
3957 for (jp = curjob; jp; jp = jp->prev_job) {
3958 if (!(mode & SHOW_CHANGED) || jp->changed)
3959 showjob(out, jp, mode);
3960 }
3961}
3962#endif /* JOBS */
3963
3964static int
3965getstatus(struct job *job)
3966{
3967 int status;
3968 int retval;
3969
3970 status = job->ps[job->nprocs - 1].status;
3971 retval = WEXITSTATUS(status);
3972 if (!WIFEXITED(status)) {
3973#if JOBS
3974 retval = WSTOPSIG(status);
3975 if (!WIFSTOPPED(status))
3976#endif
3977 {
3978 /* XXX: limits number of signals */
3979 retval = WTERMSIG(status);
3980#if JOBS
3981 if (retval == SIGINT)
3982 job->sigint = 1;
3983#endif
3984 }
3985 retval += 128;
3986 }
3987 TRACE(("getstatus: job %d, nproc %d, status %x, retval %x\n",
3988 jobno(job), job->nprocs, status, retval));
3989 return retval;
3990}
3991
3992static int
3993waitcmd(int argc, char **argv)
3994{
3995 struct job *job;
3996 int retval;
3997 struct job *jp;
3998
3999 EXSIGON;
4000
4001 nextopt(nullstr);
4002 retval = 0;
4003
4004 argv = argptr;
4005 if (!*argv) {
4006 /* wait for all jobs */
4007 for (;;) {
4008 jp = curjob;
4009 while (1) {
4010 if (!jp) {
4011 /* no running procs */
4012 goto out;
4013 }
4014 if (jp->state == JOBRUNNING)
4015 break;
4016 jp->waited = 1;
4017 jp = jp->prev_job;
4018 }
4019 dowait(DOWAIT_BLOCK, 0);
4020 }
4021 }
4022
4023 retval = 127;
4024 do {
4025 if (**argv != '%') {
4026 pid_t pid = number(*argv);
4027 job = curjob;
4028 goto start;
4029 do {
4030 if (job->ps[job->nprocs - 1].pid == pid)
4031 break;
4032 job = job->prev_job;
4033 start:
4034 if (!job)
4035 goto repeat;
4036 } while (1);
4037 } else
4038 job = getjob(*argv, 0);
4039 /* loop until process terminated or stopped */
4040 while (job->state == JOBRUNNING)
4041 dowait(DOWAIT_BLOCK, 0);
4042 job->waited = 1;
4043 retval = getstatus(job);
4044 repeat:
4045 ;
4046 } while (*++argv);
4047
4048 out:
4049 return retval;
4050}
4051
4052static struct job *
4053growjobtab(void)
4054{
4055 size_t len;
4056 ptrdiff_t offset;
4057 struct job *jp, *jq;
4058
4059 len = njobs * sizeof(*jp);
4060 jq = jobtab;
4061 jp = ckrealloc(jq, len + 4 * sizeof(*jp));
4062
4063 offset = (char *)jp - (char *)jq;
4064 if (offset) {
4065 /* Relocate pointers */
4066 size_t l = len;
4067
4068 jq = (struct job *)((char *)jq + l);
4069 while (l) {
4070 l -= sizeof(*jp);
4071 jq--;
4072#define joff(p) ((struct job *)((char *)(p) + l))
4073#define jmove(p) (p) = (void *)((char *)(p) + offset)
4074 if (joff(jp)->ps == &jq->ps0)
4075 jmove(joff(jp)->ps);
4076 if (joff(jp)->prev_job)
4077 jmove(joff(jp)->prev_job);
4078 }
4079 if (curjob)
4080 jmove(curjob);
4081#undef joff
4082#undef jmove
4083 }
4084
4085 njobs += 4;
4086 jobtab = jp;
4087 jp = (struct job *)((char *)jp + len);
4088 jq = jp + 3;
4089 do {
4090 jq->used = 0;
4091 } while (--jq >= jp);
4092 return jp;
4093}
4094
4095/*
4096 * Return a new job structure.
4097 * Called with interrupts off.
4098 */
4099static struct job *
4100makejob(union node *node, int nprocs)
4101{
4102 int i;
4103 struct job *jp;
4104
4105 for (i = njobs, jp = jobtab; ; jp++) {
4106 if (--i < 0) {
4107 jp = growjobtab();
4108 break;
4109 }
4110 if (jp->used == 0)
4111 break;
4112 if (jp->state != JOBDONE || !jp->waited)
4113 continue;
4114#if JOBS
4115 if (jobctl)
4116 continue;
4117#endif
4118 freejob(jp);
4119 break;
4120 }
4121 memset(jp, 0, sizeof(*jp));
4122#if JOBS
4123 if (jobctl)
4124 jp->jobctl = 1;
4125#endif
4126 jp->prev_job = curjob;
4127 curjob = jp;
4128 jp->used = 1;
4129 jp->ps = &jp->ps0;
4130 if (nprocs > 1) {
4131 jp->ps = ckmalloc(nprocs * sizeof(struct procstat));
4132 }
4133 TRACE(("makejob(0x%lx, %d) returns %%%d\n", (long)node, nprocs,
4134 jobno(jp)));
4135 return jp;
4136}
4137
4138#if JOBS
4139/*
4140 * Return a string identifying a command (to be printed by the
4141 * jobs command).
4142 */
4143static char *cmdnextc;
4144
4145static void
4146cmdputs(const char *s)
4147{
4148 const char *p, *str;
4149 char c, cc[2] = " ";
4150 char *nextc;
4151 int subtype = 0;
4152 int quoted = 0;
4153 static const char vstype[VSTYPE + 1][4] = {
4154 "", "}", "-", "+", "?", "=",
4155 "%", "%%", "#", "##"
4156 };
4157
4158 nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc);
4159 p = s;
4160 while ((c = *p++) != 0) {
4161 str = 0;
4162 switch (c) {
4163 case CTLESC:
4164 c = *p++;
4165 break;
4166 case CTLVAR:
4167 subtype = *p++;
4168 if ((subtype & VSTYPE) == VSLENGTH)
4169 str = "${#";
4170 else
4171 str = "${";
4172 if (!(subtype & VSQUOTE) == !(quoted & 1))
4173 goto dostr;
4174 quoted ^= 1;
4175 c = '"';
4176 break;
4177 case CTLENDVAR:
4178 str = "\"}" + !(quoted & 1);
4179 quoted >>= 1;
4180 subtype = 0;
4181 goto dostr;
4182 case CTLBACKQ:
4183 str = "$(...)";
4184 goto dostr;
4185 case CTLBACKQ+CTLQUOTE:
4186 str = "\"$(...)\"";
4187 goto dostr;
4188#if ENABLE_ASH_MATH_SUPPORT
4189 case CTLARI:
4190 str = "$((";
4191 goto dostr;
4192 case CTLENDARI:
4193 str = "))";
4194 goto dostr;
4195#endif
4196 case CTLQUOTEMARK:
4197 quoted ^= 1;
4198 c = '"';
4199 break;
4200 case '=':
4201 if (subtype == 0)
4202 break;
4203 if ((subtype & VSTYPE) != VSNORMAL)
4204 quoted <<= 1;
4205 str = vstype[subtype & VSTYPE];
4206 if (subtype & VSNUL)
4207 c = ':';
4208 else
4209 goto checkstr;
4210 break;
4211 case '\'':
4212 case '\\':
4213 case '"':
4214 case '$':
4215 /* These can only happen inside quotes */
4216 cc[0] = c;
4217 str = cc;
4218 c = '\\';
4219 break;
4220 default:
4221 break;
4222 }
4223 USTPUTC(c, nextc);
4224 checkstr:
4225 if (!str)
4226 continue;
4227 dostr:
4228 while ((c = *str++)) {
4229 USTPUTC(c, nextc);
4230 }
4231 }
4232 if (quoted & 1) {
4233 USTPUTC('"', nextc);
4234 }
4235 *nextc = 0;
4236 cmdnextc = nextc;
4237}
4238
4239/* cmdtxt() and cmdlist() call each other */
4240static void cmdtxt(union node *n);
4241
4242static void
4243cmdlist(union node *np, int sep)
4244{
4245 for (; np; np = np->narg.next) {
4246 if (!sep)
4247 cmdputs(spcstr);
4248 cmdtxt(np);
4249 if (sep && np->narg.next)
4250 cmdputs(spcstr);
4251 }
4252}
4253
4254static void
4255cmdtxt(union node *n)
4256{
4257 union node *np;
4258 struct nodelist *lp;
4259 const char *p;
4260 char s[2];
4261
4262 if (!n)
4263 return;
4264 switch (n->type) {
4265 default:
4266#if DEBUG
4267 abort();
4268#endif
4269 case NPIPE:
4270 lp = n->npipe.cmdlist;
4271 for (;;) {
4272 cmdtxt(lp->n);
4273 lp = lp->next;
4274 if (!lp)
4275 break;
4276 cmdputs(" | ");
4277 }
4278 break;
4279 case NSEMI:
4280 p = "; ";
4281 goto binop;
4282 case NAND:
4283 p = " && ";
4284 goto binop;
4285 case NOR:
4286 p = " || ";
4287 binop:
4288 cmdtxt(n->nbinary.ch1);
4289 cmdputs(p);
4290 n = n->nbinary.ch2;
4291 goto donode;
4292 case NREDIR:
4293 case NBACKGND:
4294 n = n->nredir.n;
4295 goto donode;
4296 case NNOT:
4297 cmdputs("!");
4298 n = n->nnot.com;
4299 donode:
4300 cmdtxt(n);
4301 break;
4302 case NIF:
4303 cmdputs("if ");
4304 cmdtxt(n->nif.test);
4305 cmdputs("; then ");
4306 n = n->nif.ifpart;
4307 if (n->nif.elsepart) {
4308 cmdtxt(n);
4309 cmdputs("; else ");
4310 n = n->nif.elsepart;
4311 }
4312 p = "; fi";
4313 goto dotail;
4314 case NSUBSHELL:
4315 cmdputs("(");
4316 n = n->nredir.n;
4317 p = ")";
4318 goto dotail;
4319 case NWHILE:
4320 p = "while ";
4321 goto until;
4322 case NUNTIL:
4323 p = "until ";
4324 until:
4325 cmdputs(p);
4326 cmdtxt(n->nbinary.ch1);
4327 n = n->nbinary.ch2;
4328 p = "; done";
4329 dodo:
4330 cmdputs("; do ");
4331 dotail:
4332 cmdtxt(n);
4333 goto dotail2;
4334 case NFOR:
4335 cmdputs("for ");
4336 cmdputs(n->nfor.var);
4337 cmdputs(" in ");
4338 cmdlist(n->nfor.args, 1);
4339 n = n->nfor.body;
4340 p = "; done";
4341 goto dodo;
4342 case NDEFUN:
4343 cmdputs(n->narg.text);
4344 p = "() { ... }";
4345 goto dotail2;
4346 case NCMD:
4347 cmdlist(n->ncmd.args, 1);
4348 cmdlist(n->ncmd.redirect, 0);
4349 break;
4350 case NARG:
4351 p = n->narg.text;
4352 dotail2:
4353 cmdputs(p);
4354 break;
4355 case NHERE:
4356 case NXHERE:
4357 p = "<<...";
4358 goto dotail2;
4359 case NCASE:
4360 cmdputs("case ");
4361 cmdputs(n->ncase.expr->narg.text);
4362 cmdputs(" in ");
4363 for (np = n->ncase.cases; np; np = np->nclist.next) {
4364 cmdtxt(np->nclist.pattern);
4365 cmdputs(") ");
4366 cmdtxt(np->nclist.body);
4367 cmdputs(";; ");
4368 }
4369 p = "esac";
4370 goto dotail2;
4371 case NTO:
4372 p = ">";
4373 goto redir;
4374 case NCLOBBER:
4375 p = ">|";
4376 goto redir;
4377 case NAPPEND:
4378 p = ">>";
4379 goto redir;
4380 case NTOFD:
4381 p = ">&";
4382 goto redir;
4383 case NFROM:
4384 p = "<";
4385 goto redir;
4386 case NFROMFD:
4387 p = "<&";
4388 goto redir;
4389 case NFROMTO:
4390 p = "<>";
4391 redir:
4392 s[0] = n->nfile.fd + '0';
4393 s[1] = '\0';
4394 cmdputs(s);
4395 cmdputs(p);
4396 if (n->type == NTOFD || n->type == NFROMFD) {
4397 s[0] = n->ndup.dupfd + '0';
4398 p = s;
4399 goto dotail2;
4400 }
4401 n = n->nfile.fname;
4402 goto donode;
4403 }
4404}
4405
4406static char *
4407commandtext(union node *n)
4408{
4409 char *name;
4410
4411 STARTSTACKSTR(cmdnextc);
4412 cmdtxt(n);
4413 name = stackblock();
4414 TRACE(("commandtext: name %p, end %p\n\t\"%s\"\n",
4415 name, cmdnextc, cmdnextc));
4416 return ckstrdup(name);
4417}
4418#endif /* JOBS */
4419
4420/*
4421 * Fork off a subshell. If we are doing job control, give the subshell its
4422 * own process group. Jp is a job structure that the job is to be added to.
4423 * N is the command that will be evaluated by the child. Both jp and n may
4424 * be NULL. The mode parameter can be one of the following:
4425 * FORK_FG - Fork off a foreground process.
4426 * FORK_BG - Fork off a background process.
4427 * FORK_NOJOB - Like FORK_FG, but don't give the process its own
4428 * process group even if job control is on.
4429 *
4430 * When job control is turned off, background processes have their standard
4431 * input redirected to /dev/null (except for the second and later processes
4432 * in a pipeline).
4433 *
4434 * Called with interrupts off.
4435 */
4436/*
4437 * Clear traps on a fork.
4438 */
4439static void
4440clear_traps(void)
4441{
4442 char **tp;
4443
4444 for (tp = trap; tp < &trap[NSIG]; tp++) {
4445 if (*tp && **tp) { /* trap not NULL or SIG_IGN */
4446 INT_OFF;
4447 free(*tp);
4448 *tp = NULL;
4449 if (tp != &trap[0])
4450 setsignal(tp - trap);
4451 INT_ON;
4452 }
4453 }
4454}
4455/* lives far away from here, needed for forkchild */
4456static void closescript(void);
4457static void
4458forkchild(struct job *jp, union node *n, int mode)
4459{
4460 int oldlvl;
4461
4462 TRACE(("Child shell %d\n", getpid()));
4463 oldlvl = shlvl;
4464 shlvl++;
4465
4466 closescript();
4467 clear_traps();
4468#if JOBS
4469 /* do job control only in root shell */
4470 jobctl = 0;
4471 if (mode != FORK_NOJOB && jp->jobctl && !oldlvl) {
4472 pid_t pgrp;
4473
4474 if (jp->nprocs == 0)
4475 pgrp = getpid();
4476 else
4477 pgrp = jp->ps[0].pid;
4478 /* This can fail because we are doing it in the parent also */
4479 (void)setpgid(0, pgrp);
4480 if (mode == FORK_FG)
4481 xtcsetpgrp(ttyfd, pgrp);
4482 setsignal(SIGTSTP);
4483 setsignal(SIGTTOU);
4484 } else
4485#endif
4486 if (mode == FORK_BG) {
4487 ignoresig(SIGINT);
4488 ignoresig(SIGQUIT);
4489 if (jp->nprocs == 0) {
4490 close(0);
4491 if (open(bb_dev_null, O_RDONLY) != 0)
4492 ash_msg_and_raise_error("Can't open %s", bb_dev_null);
4493 }
4494 }
4495 if (!oldlvl && iflag) {
4496 setsignal(SIGINT);
4497 setsignal(SIGQUIT);
4498 setsignal(SIGTERM);
4499 }
4500 for (jp = curjob; jp; jp = jp->prev_job)
4501 freejob(jp);
4502 jobless = 0;
4503}
4504
4505static void
4506forkparent(struct job *jp, union node *n, int mode, pid_t pid)
4507{
4508 TRACE(("In parent shell: child = %d\n", pid));
4509 if (!jp) {
4510 while (jobless && dowait(DOWAIT_NORMAL, 0) > 0);
4511 jobless++;
4512 return;
4513 }
4514#if JOBS
4515 if (mode != FORK_NOJOB && jp->jobctl) {
4516 int pgrp;
4517
4518 if (jp->nprocs == 0)
4519 pgrp = pid;
4520 else
4521 pgrp = jp->ps[0].pid;
4522 /* This can fail because we are doing it in the child also */
4523 setpgid(pid, pgrp);
4524 }
4525#endif
4526 if (mode == FORK_BG) {
4527 backgndpid = pid; /* set $! */
4528 set_curjob(jp, CUR_RUNNING);
4529 }
4530 if (jp) {
4531 struct procstat *ps = &jp->ps[jp->nprocs++];
4532 ps->pid = pid;
4533 ps->status = -1;
4534 ps->cmd = nullstr;
4535#if JOBS
4536 if (jobctl && n)
4537 ps->cmd = commandtext(n);
4538#endif
4539 }
4540}
4541
4542static int
4543forkshell(struct job *jp, union node *n, int mode)
4544{
4545 int pid;
4546
4547 TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode));
4548 pid = fork();
4549 if (pid < 0) {
4550 TRACE(("Fork failed, errno=%d", errno));
4551 if (jp)
4552 freejob(jp);
4553 ash_msg_and_raise_error("Cannot fork");
4554 }
4555 if (pid == 0)
4556 forkchild(jp, n, mode);
4557 else
4558 forkparent(jp, n, mode, pid);
4559 return pid;
4560}
4561
4562/*
4563 * Wait for job to finish.
4564 *
4565 * Under job control we have the problem that while a child process is
4566 * running interrupts generated by the user are sent to the child but not
4567 * to the shell. This means that an infinite loop started by an inter-
4568 * active user may be hard to kill. With job control turned off, an
4569 * interactive user may place an interactive program inside a loop. If
4570 * the interactive program catches interrupts, the user doesn't want
4571 * these interrupts to also abort the loop. The approach we take here
4572 * is to have the shell ignore interrupt signals while waiting for a
4573 * foreground process to terminate, and then send itself an interrupt
4574 * signal if the child process was terminated by an interrupt signal.
4575 * Unfortunately, some programs want to do a bit of cleanup and then
4576 * exit on interrupt; unless these processes terminate themselves by
4577 * sending a signal to themselves (instead of calling exit) they will
4578 * confuse this approach.
4579 *
4580 * Called with interrupts off.
4581 */
4582static int
4583waitforjob(struct job *jp)
4584{
4585 int st;
4586
4587 TRACE(("waitforjob(%%%d) called\n", jobno(jp)));
4588 while (jp->state == JOBRUNNING) {
4589 dowait(DOWAIT_BLOCK, jp);
4590 }
4591 st = getstatus(jp);
4592#if JOBS
4593 if (jp->jobctl) {
4594 xtcsetpgrp(ttyfd, rootpid);
4595 /*
4596 * This is truly gross.
4597 * If we're doing job control, then we did a TIOCSPGRP which
4598 * caused us (the shell) to no longer be in the controlling
4599 * session -- so we wouldn't have seen any ^C/SIGINT. So, we
4600 * intuit from the subprocess exit status whether a SIGINT
4601 * occurred, and if so interrupt ourselves. Yuck. - mycroft
4602 */
4603 if (jp->sigint)
4604 raise(SIGINT);
4605 }
4606 if (jp->state == JOBDONE)
4607#endif
4608 freejob(jp);
4609 return st;
4610}
4611
4612/*
4613 * return 1 if there are stopped jobs, otherwise 0
4614 */
4615static int
4616stoppedjobs(void)
4617{
4618 struct job *jp;
4619 int retval;
4620
4621 retval = 0;
4622 if (job_warning)
4623 goto out;
4624 jp = curjob;
4625 if (jp && jp->state == JOBSTOPPED) {
4626 out2str("You have stopped jobs.\n");
4627 job_warning = 2;
4628 retval++;
4629 }
4630 out:
4631 return retval;
4632}
4633
4634
3162/* ============ Routines to expand arguments to commands 4635/* ============ Routines to expand arguments to commands
3163 * 4636 *
3164 * We have to deal with backquotes, shell variables, and file metacharacters. 4637 * We have to deal with backquotes, shell variables, and file metacharacters.
@@ -7333,1470 +8806,6 @@ setinputstring(char *string)
7333} 8806}
7334 8807
7335 8808
7336/* ============ jobs.c */
7337
7338/*
7339 * Set the signal handler for the specified signal. The routine figures
7340 * out what it should be set to.
7341 */
7342static void
7343setsignal(int signo)
7344{
7345 int action;
7346 char *t, tsig;
7347 struct sigaction act;
7348
7349 t = trap[signo];
7350 if (t == NULL)
7351 action = S_DFL;
7352 else if (*t != '\0')
7353 action = S_CATCH;
7354 else
7355 action = S_IGN;
7356 if (rootshell && action == S_DFL) {
7357 switch (signo) {
7358 case SIGINT:
7359 if (iflag || minusc || sflag == 0)
7360 action = S_CATCH;
7361 break;
7362 case SIGQUIT:
7363#if DEBUG
7364 if (debug)
7365 break;
7366#endif
7367 /* FALLTHROUGH */
7368 case SIGTERM:
7369 if (iflag)
7370 action = S_IGN;
7371 break;
7372#if JOBS
7373 case SIGTSTP:
7374 case SIGTTOU:
7375 if (mflag)
7376 action = S_IGN;
7377 break;
7378#endif
7379 }
7380 }
7381
7382 t = &sigmode[signo - 1];
7383 tsig = *t;
7384 if (tsig == 0) {
7385 /*
7386 * current setting unknown
7387 */
7388 if (sigaction(signo, 0, &act) == -1) {
7389 /*
7390 * Pretend it worked; maybe we should give a warning
7391 * here, but other shells don't. We don't alter
7392 * sigmode, so that we retry every time.
7393 */
7394 return;
7395 }
7396 if (act.sa_handler == SIG_IGN) {
7397 if (mflag
7398 && (signo == SIGTSTP || signo == SIGTTIN || signo == SIGTTOU)
7399 ) {
7400 tsig = S_IGN; /* don't hard ignore these */
7401 } else
7402 tsig = S_HARD_IGN;
7403 } else {
7404 tsig = S_RESET; /* force to be set */
7405 }
7406 }
7407 if (tsig == S_HARD_IGN || tsig == action)
7408 return;
7409 switch (action) {
7410 case S_CATCH:
7411 act.sa_handler = onsig;
7412 break;
7413 case S_IGN:
7414 act.sa_handler = SIG_IGN;
7415 break;
7416 default:
7417 act.sa_handler = SIG_DFL;
7418 }
7419 *t = action;
7420 act.sa_flags = 0;
7421 sigfillset(&act.sa_mask);
7422 sigaction(signo, &act, 0);
7423}
7424
7425/* mode flags for set_curjob */
7426#define CUR_DELETE 2
7427#define CUR_RUNNING 1
7428#define CUR_STOPPED 0
7429
7430/* mode flags for dowait */
7431#define DOWAIT_NORMAL 0
7432#define DOWAIT_BLOCK 1
7433
7434#if JOBS
7435/* pgrp of shell on invocation */
7436static int initialpgrp;
7437static int ttyfd = -1;
7438#endif
7439/* array of jobs */
7440static struct job *jobtab;
7441/* size of array */
7442static unsigned njobs;
7443/* current job */
7444static struct job *curjob;
7445/* number of presumed living untracked jobs */
7446static int jobless;
7447
7448static void
7449set_curjob(struct job *jp, unsigned mode)
7450{
7451 struct job *jp1;
7452 struct job **jpp, **curp;
7453
7454 /* first remove from list */
7455 jpp = curp = &curjob;
7456 do {
7457 jp1 = *jpp;
7458 if (jp1 == jp)
7459 break;
7460 jpp = &jp1->prev_job;
7461 } while (1);
7462 *jpp = jp1->prev_job;
7463
7464 /* Then re-insert in correct position */
7465 jpp = curp;
7466 switch (mode) {
7467 default:
7468#if DEBUG
7469 abort();
7470#endif
7471 case CUR_DELETE:
7472 /* job being deleted */
7473 break;
7474 case CUR_RUNNING:
7475 /* newly created job or backgrounded job,
7476 put after all stopped jobs. */
7477 do {
7478 jp1 = *jpp;
7479#if JOBS
7480 if (!jp1 || jp1->state != JOBSTOPPED)
7481#endif
7482 break;
7483 jpp = &jp1->prev_job;
7484 } while (1);
7485 /* FALLTHROUGH */
7486#if JOBS
7487 case CUR_STOPPED:
7488#endif
7489 /* newly stopped job - becomes curjob */
7490 jp->prev_job = *jpp;
7491 *jpp = jp;
7492 break;
7493 }
7494}
7495
7496#if JOBS || DEBUG
7497static int
7498jobno(const struct job *jp)
7499{
7500 return jp - jobtab + 1;
7501}
7502#endif
7503
7504/*
7505 * Convert a job name to a job structure.
7506 */
7507static struct job *
7508getjob(const char *name, int getctl)
7509{
7510 struct job *jp;
7511 struct job *found;
7512 const char *err_msg = "No such job: %s";
7513 unsigned num;
7514 int c;
7515 const char *p;
7516 char *(*match)(const char *, const char *);
7517
7518 jp = curjob;
7519 p = name;
7520 if (!p)
7521 goto currentjob;
7522
7523 if (*p != '%')
7524 goto err;
7525
7526 c = *++p;
7527 if (!c)
7528 goto currentjob;
7529
7530 if (!p[1]) {
7531 if (c == '+' || c == '%') {
7532 currentjob:
7533 err_msg = "No current job";
7534 goto check;
7535 }
7536 if (c == '-') {
7537 if (jp)
7538 jp = jp->prev_job;
7539 err_msg = "No previous job";
7540 check:
7541 if (!jp)
7542 goto err;
7543 goto gotit;
7544 }
7545 }
7546
7547 if (is_number(p)) {
7548 num = atoi(p);
7549 if (num < njobs) {
7550 jp = jobtab + num - 1;
7551 if (jp->used)
7552 goto gotit;
7553 goto err;
7554 }
7555 }
7556
7557 match = prefix;
7558 if (*p == '?') {
7559 match = strstr;
7560 p++;
7561 }
7562
7563 found = 0;
7564 while (1) {
7565 if (!jp)
7566 goto err;
7567 if (match(jp->ps[0].cmd, p)) {
7568 if (found)
7569 goto err;
7570 found = jp;
7571 err_msg = "%s: ambiguous";
7572 }
7573 jp = jp->prev_job;
7574 }
7575
7576 gotit:
7577#if JOBS
7578 err_msg = "job %s not created under job control";
7579 if (getctl && jp->jobctl == 0)
7580 goto err;
7581#endif
7582 return jp;
7583 err:
7584 ash_msg_and_raise_error(err_msg, name);
7585}
7586
7587/*
7588 * Mark a job structure as unused.
7589 */
7590static void
7591freejob(struct job *jp)
7592{
7593 struct procstat *ps;
7594 int i;
7595
7596 INT_OFF;
7597 for (i = jp->nprocs, ps = jp->ps; --i >= 0; ps++) {
7598 if (ps->cmd != nullstr)
7599 free(ps->cmd);
7600 }
7601 if (jp->ps != &jp->ps0)
7602 free(jp->ps);
7603 jp->used = 0;
7604 set_curjob(jp, CUR_DELETE);
7605 INT_ON;
7606}
7607
7608#if JOBS
7609static void
7610xtcsetpgrp(int fd, pid_t pgrp)
7611{
7612 if (tcsetpgrp(fd, pgrp))
7613 ash_msg_and_raise_error("Cannot set tty process group (%m)");
7614}
7615
7616/*
7617 * Turn job control on and off.
7618 *
7619 * Note: This code assumes that the third arg to ioctl is a character
7620 * pointer, which is true on Berkeley systems but not System V. Since
7621 * System V doesn't have job control yet, this isn't a problem now.
7622 *
7623 * Called with interrupts off.
7624 */
7625static void
7626setjobctl(int on)
7627{
7628 int fd;
7629 int pgrp;
7630
7631 if (on == jobctl || rootshell == 0)
7632 return;
7633 if (on) {
7634 int ofd;
7635 ofd = fd = open(_PATH_TTY, O_RDWR);
7636 if (fd < 0) {
7637 /* BTW, bash will try to open(ttyname(0)) if open("/dev/tty") fails.
7638 * That sometimes helps to acquire controlling tty.
7639 * Obviously, a workaround for bugs when someone
7640 * failed to provide a controlling tty to bash! :) */
7641 fd += 3;
7642 while (!isatty(fd) && --fd >= 0)
7643 ;
7644 }
7645 fd = fcntl(fd, F_DUPFD, 10);
7646 close(ofd);
7647 if (fd < 0)
7648 goto out;
7649 fcntl(fd, F_SETFD, FD_CLOEXEC);
7650 do { /* while we are in the background */
7651 pgrp = tcgetpgrp(fd);
7652 if (pgrp < 0) {
7653 out:
7654 ash_msg("can't access tty; job control turned off");
7655 mflag = on = 0;
7656 goto close;
7657 }
7658 if (pgrp == getpgrp())
7659 break;
7660 killpg(0, SIGTTIN);
7661 } while (1);
7662 initialpgrp = pgrp;
7663
7664 setsignal(SIGTSTP);
7665 setsignal(SIGTTOU);
7666 setsignal(SIGTTIN);
7667 pgrp = rootpid;
7668 setpgid(0, pgrp);
7669 xtcsetpgrp(fd, pgrp);
7670 } else {
7671 /* turning job control off */
7672 fd = ttyfd;
7673 pgrp = initialpgrp;
7674 xtcsetpgrp(fd, pgrp);
7675 setpgid(0, pgrp);
7676 setsignal(SIGTSTP);
7677 setsignal(SIGTTOU);
7678 setsignal(SIGTTIN);
7679 close:
7680 close(fd);
7681 fd = -1;
7682 }
7683 ttyfd = fd;
7684 jobctl = on;
7685}
7686
7687static int
7688killcmd(int argc, char **argv)
7689{
7690 int signo = -1;
7691 int list = 0;
7692 int i;
7693 pid_t pid;
7694 struct job *jp;
7695
7696 if (argc <= 1) {
7697 usage:
7698 ash_msg_and_raise_error(
7699"Usage: kill [-s sigspec | -signum | -sigspec] [pid | job]... or\n"
7700"kill -l [exitstatus]"
7701 );
7702 }
7703
7704 if (**++argv == '-') {
7705 signo = get_signum(*argv + 1);
7706 if (signo < 0) {
7707 int c;
7708
7709 while ((c = nextopt("ls:")) != '\0') {
7710 switch (c) {
7711 default:
7712#if DEBUG
7713 abort();
7714#endif
7715 case 'l':
7716 list = 1;
7717 break;
7718 case 's':
7719 signo = get_signum(optionarg);
7720 if (signo < 0) {
7721 ash_msg_and_raise_error(
7722 "invalid signal number or name: %s",
7723 optionarg
7724 );
7725 }
7726 break;
7727 }
7728 }
7729 argv = argptr;
7730 } else
7731 argv++;
7732 }
7733
7734 if (!list && signo < 0)
7735 signo = SIGTERM;
7736
7737 if ((signo < 0 || !*argv) ^ list) {
7738 goto usage;
7739 }
7740
7741 if (list) {
7742 const char *name;
7743
7744 if (!*argv) {
7745 for (i = 1; i < NSIG; i++) {
7746 name = get_signame(i);
7747 if (isdigit(*name))
7748 out1fmt(snlfmt, name);
7749 }
7750 return 0;
7751 }
7752 name = get_signame(signo);
7753 if (!isdigit(*name))
7754 ash_msg_and_raise_error("invalid signal number or exit status: %s", *argptr);
7755 out1fmt(snlfmt, name);
7756 return 0;
7757 }
7758
7759 i = 0;
7760 do {
7761 if (**argv == '%') {
7762 jp = getjob(*argv, 0);
7763 pid = -jp->ps[0].pid;
7764 } else {
7765 pid = **argv == '-' ?
7766 -number(*argv + 1) : number(*argv);
7767 }
7768 if (kill(pid, signo) != 0) {
7769 ash_msg("(%d) - %m", pid);
7770 i = 1;
7771 }
7772 } while (*++argv);
7773
7774 return i;
7775}
7776
7777static void
7778showpipe(struct job *jp, FILE *out)
7779{
7780 struct procstat *sp;
7781 struct procstat *spend;
7782
7783 spend = jp->ps + jp->nprocs;
7784 for (sp = jp->ps + 1; sp < spend; sp++)
7785 fprintf(out, " | %s", sp->cmd);
7786 outcslow('\n', out);
7787 flush_stdout_stderr();
7788}
7789
7790
7791static int
7792restartjob(struct job *jp, int mode)
7793{
7794 struct procstat *ps;
7795 int i;
7796 int status;
7797 pid_t pgid;
7798
7799 INT_OFF;
7800 if (jp->state == JOBDONE)
7801 goto out;
7802 jp->state = JOBRUNNING;
7803 pgid = jp->ps->pid;
7804 if (mode == FORK_FG)
7805 xtcsetpgrp(ttyfd, pgid);
7806 killpg(pgid, SIGCONT);
7807 ps = jp->ps;
7808 i = jp->nprocs;
7809 do {
7810 if (WIFSTOPPED(ps->status)) {
7811 ps->status = -1;
7812 }
7813 } while (ps++, --i);
7814 out:
7815 status = (mode == FORK_FG) ? waitforjob(jp) : 0;
7816 INT_ON;
7817 return status;
7818}
7819
7820static int
7821fg_bgcmd(int argc, char **argv)
7822{
7823 struct job *jp;
7824 FILE *out;
7825 int mode;
7826 int retval;
7827
7828 mode = (**argv == 'f') ? FORK_FG : FORK_BG;
7829 nextopt(nullstr);
7830 argv = argptr;
7831 out = stdout;
7832 do {
7833 jp = getjob(*argv, 1);
7834 if (mode == FORK_BG) {
7835 set_curjob(jp, CUR_RUNNING);
7836 fprintf(out, "[%d] ", jobno(jp));
7837 }
7838 outstr(jp->ps->cmd, out);
7839 showpipe(jp, out);
7840 retval = restartjob(jp, mode);
7841 } while (*argv && *++argv);
7842 return retval;
7843}
7844#endif
7845
7846static int
7847sprint_status(char *s, int status, int sigonly)
7848{
7849 int col;
7850 int st;
7851
7852 col = 0;
7853 if (!WIFEXITED(status)) {
7854#if JOBS
7855 if (WIFSTOPPED(status))
7856 st = WSTOPSIG(status);
7857 else
7858#endif
7859 st = WTERMSIG(status);
7860 if (sigonly) {
7861 if (st == SIGINT || st == SIGPIPE)
7862 goto out;
7863#if JOBS
7864 if (WIFSTOPPED(status))
7865 goto out;
7866#endif
7867 }
7868 st &= 0x7f;
7869 col = fmtstr(s, 32, strsignal(st));
7870 if (WCOREDUMP(status)) {
7871 col += fmtstr(s + col, 16, " (core dumped)");
7872 }
7873 } else if (!sigonly) {
7874 st = WEXITSTATUS(status);
7875 if (st)
7876 col = fmtstr(s, 16, "Done(%d)", st);
7877 else
7878 col = fmtstr(s, 16, "Done");
7879 }
7880 out:
7881 return col;
7882}
7883
7884/*
7885 * Do a wait system call. If job control is compiled in, we accept
7886 * stopped processes. If block is zero, we return a value of zero
7887 * rather than blocking.
7888 *
7889 * System V doesn't have a non-blocking wait system call. It does
7890 * have a SIGCLD signal that is sent to a process when one of it's
7891 * children dies. The obvious way to use SIGCLD would be to install
7892 * a handler for SIGCLD which simply bumped a counter when a SIGCLD
7893 * was received, and have waitproc bump another counter when it got
7894 * the status of a process. Waitproc would then know that a wait
7895 * system call would not block if the two counters were different.
7896 * This approach doesn't work because if a process has children that
7897 * have not been waited for, System V will send it a SIGCLD when it
7898 * installs a signal handler for SIGCLD. What this means is that when
7899 * a child exits, the shell will be sent SIGCLD signals continuously
7900 * until is runs out of stack space, unless it does a wait call before
7901 * restoring the signal handler. The code below takes advantage of
7902 * this (mis)feature by installing a signal handler for SIGCLD and
7903 * then checking to see whether it was called. If there are any
7904 * children to be waited for, it will be.
7905 *
7906 * If neither SYSV nor BSD is defined, we don't implement nonblocking
7907 * waits at all. In this case, the user will not be informed when
7908 * a background process until the next time she runs a real program
7909 * (as opposed to running a builtin command or just typing return),
7910 * and the jobs command may give out of date information.
7911 */
7912static int
7913waitproc(int block, int *status)
7914{
7915 int flags = 0;
7916
7917#if JOBS
7918 if (jobctl)
7919 flags |= WUNTRACED;
7920#endif
7921 if (block == 0)
7922 flags |= WNOHANG;
7923 return wait3(status, flags, (struct rusage *)NULL);
7924}
7925
7926/*
7927 * Wait for a process to terminate.
7928 */
7929static int
7930dowait(int block, struct job *job)
7931{
7932 int pid;
7933 int status;
7934 struct job *jp;
7935 struct job *thisjob;
7936 int state;
7937
7938 TRACE(("dowait(%d) called\n", block));
7939 pid = waitproc(block, &status);
7940 TRACE(("wait returns pid %d, status=%d\n", pid, status));
7941 if (pid <= 0)
7942 return pid;
7943 INT_OFF;
7944 thisjob = NULL;
7945 for (jp = curjob; jp; jp = jp->prev_job) {
7946 struct procstat *sp;
7947 struct procstat *spend;
7948 if (jp->state == JOBDONE)
7949 continue;
7950 state = JOBDONE;
7951 spend = jp->ps + jp->nprocs;
7952 sp = jp->ps;
7953 do {
7954 if (sp->pid == pid) {
7955 TRACE(("Job %d: changing status of proc %d "
7956 "from 0x%x to 0x%x\n",
7957 jobno(jp), pid, sp->status, status));
7958 sp->status = status;
7959 thisjob = jp;
7960 }
7961 if (sp->status == -1)
7962 state = JOBRUNNING;
7963#if JOBS
7964 if (state == JOBRUNNING)
7965 continue;
7966 if (WIFSTOPPED(sp->status)) {
7967 jp->stopstatus = sp->status;
7968 state = JOBSTOPPED;
7969 }
7970#endif
7971 } while (++sp < spend);
7972 if (thisjob)
7973 goto gotjob;
7974 }
7975#if JOBS
7976 if (!WIFSTOPPED(status))
7977#endif
7978
7979 jobless--;
7980 goto out;
7981
7982 gotjob:
7983 if (state != JOBRUNNING) {
7984 thisjob->changed = 1;
7985
7986 if (thisjob->state != state) {
7987 TRACE(("Job %d: changing state from %d to %d\n",
7988 jobno(thisjob), thisjob->state, state));
7989 thisjob->state = state;
7990#if JOBS
7991 if (state == JOBSTOPPED) {
7992 set_curjob(thisjob, CUR_STOPPED);
7993 }
7994#endif
7995 }
7996 }
7997
7998 out:
7999 INT_ON;
8000
8001 if (thisjob && thisjob == job) {
8002 char s[48 + 1];
8003 int len;
8004
8005 len = sprint_status(s, status, 1);
8006 if (len) {
8007 s[len] = '\n';
8008 s[len + 1] = 0;
8009 out2str(s);
8010 }
8011 }
8012 return pid;
8013}
8014
8015#if JOBS
8016static void
8017showjob(FILE *out, struct job *jp, int mode)
8018{
8019 struct procstat *ps;
8020 struct procstat *psend;
8021 int col;
8022 int indent;
8023 char s[80];
8024
8025 ps = jp->ps;
8026
8027 if (mode & SHOW_PGID) {
8028 /* just output process (group) id of pipeline */
8029 fprintf(out, "%d\n", ps->pid);
8030 return;
8031 }
8032
8033 col = fmtstr(s, 16, "[%d] ", jobno(jp));
8034 indent = col;
8035
8036 if (jp == curjob)
8037 s[col - 2] = '+';
8038 else if (curjob && jp == curjob->prev_job)
8039 s[col - 2] = '-';
8040
8041 if (mode & SHOW_PID)
8042 col += fmtstr(s + col, 16, "%d ", ps->pid);
8043
8044 psend = ps + jp->nprocs;
8045
8046 if (jp->state == JOBRUNNING) {
8047 strcpy(s + col, "Running");
8048 col += sizeof("Running") - 1;
8049 } else {
8050 int status = psend[-1].status;
8051 if (jp->state == JOBSTOPPED)
8052 status = jp->stopstatus;
8053 col += sprint_status(s + col, status, 0);
8054 }
8055
8056 goto start;
8057
8058 do {
8059 /* for each process */
8060 col = fmtstr(s, 48, " |\n%*c%d ", indent, ' ', ps->pid) - 3;
8061 start:
8062 fprintf(out, "%s%*c%s",
8063 s, 33 - col >= 0 ? 33 - col : 0, ' ', ps->cmd
8064 );
8065 if (!(mode & SHOW_PID)) {
8066 showpipe(jp, out);
8067 break;
8068 }
8069 if (++ps == psend) {
8070 outcslow('\n', out);
8071 break;
8072 }
8073 } while (1);
8074
8075 jp->changed = 0;
8076
8077 if (jp->state == JOBDONE) {
8078 TRACE(("showjob: freeing job %d\n", jobno(jp)));
8079 freejob(jp);
8080 }
8081}
8082
8083static int
8084jobscmd(int argc, char **argv)
8085{
8086 int mode, m;
8087 FILE *out;
8088
8089 mode = 0;
8090 while ((m = nextopt("lp"))) {
8091 if (m == 'l')
8092 mode = SHOW_PID;
8093 else
8094 mode = SHOW_PGID;
8095 }
8096
8097 out = stdout;
8098 argv = argptr;
8099 if (*argv) {
8100 do
8101 showjob(out, getjob(*argv,0), mode);
8102 while (*++argv);
8103 } else
8104 showjobs(out, mode);
8105
8106 return 0;
8107}
8108
8109/*
8110 * Print a list of jobs. If "change" is nonzero, only print jobs whose
8111 * statuses have changed since the last call to showjobs.
8112 */
8113static void
8114showjobs(FILE *out, int mode)
8115{
8116 struct job *jp;
8117
8118 TRACE(("showjobs(%x) called\n", mode));
8119
8120 /* If not even one one job changed, there is nothing to do */
8121 while (dowait(DOWAIT_NORMAL, NULL) > 0)
8122 continue;
8123
8124 for (jp = curjob; jp; jp = jp->prev_job) {
8125 if (!(mode & SHOW_CHANGED) || jp->changed)
8126 showjob(out, jp, mode);
8127 }
8128}
8129#endif /* JOBS */
8130
8131static int
8132getstatus(struct job *job)
8133{
8134 int status;
8135 int retval;
8136
8137 status = job->ps[job->nprocs - 1].status;
8138 retval = WEXITSTATUS(status);
8139 if (!WIFEXITED(status)) {
8140#if JOBS
8141 retval = WSTOPSIG(status);
8142 if (!WIFSTOPPED(status))
8143#endif
8144 {
8145 /* XXX: limits number of signals */
8146 retval = WTERMSIG(status);
8147#if JOBS
8148 if (retval == SIGINT)
8149 job->sigint = 1;
8150#endif
8151 }
8152 retval += 128;
8153 }
8154 TRACE(("getstatus: job %d, nproc %d, status %x, retval %x\n",
8155 jobno(job), job->nprocs, status, retval));
8156 return retval;
8157}
8158
8159static int
8160waitcmd(int argc, char **argv)
8161{
8162 struct job *job;
8163 int retval;
8164 struct job *jp;
8165
8166 EXSIGON;
8167
8168 nextopt(nullstr);
8169 retval = 0;
8170
8171 argv = argptr;
8172 if (!*argv) {
8173 /* wait for all jobs */
8174 for (;;) {
8175 jp = curjob;
8176 while (1) {
8177 if (!jp) {
8178 /* no running procs */
8179 goto out;
8180 }
8181 if (jp->state == JOBRUNNING)
8182 break;
8183 jp->waited = 1;
8184 jp = jp->prev_job;
8185 }
8186 dowait(DOWAIT_BLOCK, 0);
8187 }
8188 }
8189
8190 retval = 127;
8191 do {
8192 if (**argv != '%') {
8193 pid_t pid = number(*argv);
8194 job = curjob;
8195 goto start;
8196 do {
8197 if (job->ps[job->nprocs - 1].pid == pid)
8198 break;
8199 job = job->prev_job;
8200 start:
8201 if (!job)
8202 goto repeat;
8203 } while (1);
8204 } else
8205 job = getjob(*argv, 0);
8206 /* loop until process terminated or stopped */
8207 while (job->state == JOBRUNNING)
8208 dowait(DOWAIT_BLOCK, 0);
8209 job->waited = 1;
8210 retval = getstatus(job);
8211 repeat:
8212 ;
8213 } while (*++argv);
8214
8215 out:
8216 return retval;
8217}
8218
8219static struct job *
8220growjobtab(void)
8221{
8222 size_t len;
8223 ptrdiff_t offset;
8224 struct job *jp, *jq;
8225
8226 len = njobs * sizeof(*jp);
8227 jq = jobtab;
8228 jp = ckrealloc(jq, len + 4 * sizeof(*jp));
8229
8230 offset = (char *)jp - (char *)jq;
8231 if (offset) {
8232 /* Relocate pointers */
8233 size_t l = len;
8234
8235 jq = (struct job *)((char *)jq + l);
8236 while (l) {
8237 l -= sizeof(*jp);
8238 jq--;
8239#define joff(p) ((struct job *)((char *)(p) + l))
8240#define jmove(p) (p) = (void *)((char *)(p) + offset)
8241 if (joff(jp)->ps == &jq->ps0)
8242 jmove(joff(jp)->ps);
8243 if (joff(jp)->prev_job)
8244 jmove(joff(jp)->prev_job);
8245 }
8246 if (curjob)
8247 jmove(curjob);
8248#undef joff
8249#undef jmove
8250 }
8251
8252 njobs += 4;
8253 jobtab = jp;
8254 jp = (struct job *)((char *)jp + len);
8255 jq = jp + 3;
8256 do {
8257 jq->used = 0;
8258 } while (--jq >= jp);
8259 return jp;
8260}
8261
8262/*
8263 * Return a new job structure.
8264 * Called with interrupts off.
8265 */
8266static struct job *
8267makejob(union node *node, int nprocs)
8268{
8269 int i;
8270 struct job *jp;
8271
8272 for (i = njobs, jp = jobtab; ; jp++) {
8273 if (--i < 0) {
8274 jp = growjobtab();
8275 break;
8276 }
8277 if (jp->used == 0)
8278 break;
8279 if (jp->state != JOBDONE || !jp->waited)
8280 continue;
8281#if JOBS
8282 if (jobctl)
8283 continue;
8284#endif
8285 freejob(jp);
8286 break;
8287 }
8288 memset(jp, 0, sizeof(*jp));
8289#if JOBS
8290 if (jobctl)
8291 jp->jobctl = 1;
8292#endif
8293 jp->prev_job = curjob;
8294 curjob = jp;
8295 jp->used = 1;
8296 jp->ps = &jp->ps0;
8297 if (nprocs > 1) {
8298 jp->ps = ckmalloc(nprocs * sizeof(struct procstat));
8299 }
8300 TRACE(("makejob(0x%lx, %d) returns %%%d\n", (long)node, nprocs,
8301 jobno(jp)));
8302 return jp;
8303}
8304
8305#if JOBS
8306/*
8307 * Return a string identifying a command (to be printed by the
8308 * jobs command).
8309 */
8310static char *cmdnextc;
8311
8312static void
8313cmdputs(const char *s)
8314{
8315 const char *p, *str;
8316 char c, cc[2] = " ";
8317 char *nextc;
8318 int subtype = 0;
8319 int quoted = 0;
8320 static const char vstype[VSTYPE + 1][4] = {
8321 "", "}", "-", "+", "?", "=",
8322 "%", "%%", "#", "##"
8323 };
8324
8325 nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc);
8326 p = s;
8327 while ((c = *p++) != 0) {
8328 str = 0;
8329 switch (c) {
8330 case CTLESC:
8331 c = *p++;
8332 break;
8333 case CTLVAR:
8334 subtype = *p++;
8335 if ((subtype & VSTYPE) == VSLENGTH)
8336 str = "${#";
8337 else
8338 str = "${";
8339 if (!(subtype & VSQUOTE) == !(quoted & 1))
8340 goto dostr;
8341 quoted ^= 1;
8342 c = '"';
8343 break;
8344 case CTLENDVAR:
8345 str = "\"}" + !(quoted & 1);
8346 quoted >>= 1;
8347 subtype = 0;
8348 goto dostr;
8349 case CTLBACKQ:
8350 str = "$(...)";
8351 goto dostr;
8352 case CTLBACKQ+CTLQUOTE:
8353 str = "\"$(...)\"";
8354 goto dostr;
8355#if ENABLE_ASH_MATH_SUPPORT
8356 case CTLARI:
8357 str = "$((";
8358 goto dostr;
8359 case CTLENDARI:
8360 str = "))";
8361 goto dostr;
8362#endif
8363 case CTLQUOTEMARK:
8364 quoted ^= 1;
8365 c = '"';
8366 break;
8367 case '=':
8368 if (subtype == 0)
8369 break;
8370 if ((subtype & VSTYPE) != VSNORMAL)
8371 quoted <<= 1;
8372 str = vstype[subtype & VSTYPE];
8373 if (subtype & VSNUL)
8374 c = ':';
8375 else
8376 goto checkstr;
8377 break;
8378 case '\'':
8379 case '\\':
8380 case '"':
8381 case '$':
8382 /* These can only happen inside quotes */
8383 cc[0] = c;
8384 str = cc;
8385 c = '\\';
8386 break;
8387 default:
8388 break;
8389 }
8390 USTPUTC(c, nextc);
8391 checkstr:
8392 if (!str)
8393 continue;
8394 dostr:
8395 while ((c = *str++)) {
8396 USTPUTC(c, nextc);
8397 }
8398 }
8399 if (quoted & 1) {
8400 USTPUTC('"', nextc);
8401 }
8402 *nextc = 0;
8403 cmdnextc = nextc;
8404}
8405
8406/* cmdtxt() and cmdlist() call each other */
8407static void cmdtxt(union node *n);
8408
8409static void
8410cmdlist(union node *np, int sep)
8411{
8412 for (; np; np = np->narg.next) {
8413 if (!sep)
8414 cmdputs(spcstr);
8415 cmdtxt(np);
8416 if (sep && np->narg.next)
8417 cmdputs(spcstr);
8418 }
8419}
8420
8421static void
8422cmdtxt(union node *n)
8423{
8424 union node *np;
8425 struct nodelist *lp;
8426 const char *p;
8427 char s[2];
8428
8429 if (!n)
8430 return;
8431 switch (n->type) {
8432 default:
8433#if DEBUG
8434 abort();
8435#endif
8436 case NPIPE:
8437 lp = n->npipe.cmdlist;
8438 for (;;) {
8439 cmdtxt(lp->n);
8440 lp = lp->next;
8441 if (!lp)
8442 break;
8443 cmdputs(" | ");
8444 }
8445 break;
8446 case NSEMI:
8447 p = "; ";
8448 goto binop;
8449 case NAND:
8450 p = " && ";
8451 goto binop;
8452 case NOR:
8453 p = " || ";
8454 binop:
8455 cmdtxt(n->nbinary.ch1);
8456 cmdputs(p);
8457 n = n->nbinary.ch2;
8458 goto donode;
8459 case NREDIR:
8460 case NBACKGND:
8461 n = n->nredir.n;
8462 goto donode;
8463 case NNOT:
8464 cmdputs("!");
8465 n = n->nnot.com;
8466 donode:
8467 cmdtxt(n);
8468 break;
8469 case NIF:
8470 cmdputs("if ");
8471 cmdtxt(n->nif.test);
8472 cmdputs("; then ");
8473 n = n->nif.ifpart;
8474 if (n->nif.elsepart) {
8475 cmdtxt(n);
8476 cmdputs("; else ");
8477 n = n->nif.elsepart;
8478 }
8479 p = "; fi";
8480 goto dotail;
8481 case NSUBSHELL:
8482 cmdputs("(");
8483 n = n->nredir.n;
8484 p = ")";
8485 goto dotail;
8486 case NWHILE:
8487 p = "while ";
8488 goto until;
8489 case NUNTIL:
8490 p = "until ";
8491 until:
8492 cmdputs(p);
8493 cmdtxt(n->nbinary.ch1);
8494 n = n->nbinary.ch2;
8495 p = "; done";
8496 dodo:
8497 cmdputs("; do ");
8498 dotail:
8499 cmdtxt(n);
8500 goto dotail2;
8501 case NFOR:
8502 cmdputs("for ");
8503 cmdputs(n->nfor.var);
8504 cmdputs(" in ");
8505 cmdlist(n->nfor.args, 1);
8506 n = n->nfor.body;
8507 p = "; done";
8508 goto dodo;
8509 case NDEFUN:
8510 cmdputs(n->narg.text);
8511 p = "() { ... }";
8512 goto dotail2;
8513 case NCMD:
8514 cmdlist(n->ncmd.args, 1);
8515 cmdlist(n->ncmd.redirect, 0);
8516 break;
8517 case NARG:
8518 p = n->narg.text;
8519 dotail2:
8520 cmdputs(p);
8521 break;
8522 case NHERE:
8523 case NXHERE:
8524 p = "<<...";
8525 goto dotail2;
8526 case NCASE:
8527 cmdputs("case ");
8528 cmdputs(n->ncase.expr->narg.text);
8529 cmdputs(" in ");
8530 for (np = n->ncase.cases; np; np = np->nclist.next) {
8531 cmdtxt(np->nclist.pattern);
8532 cmdputs(") ");
8533 cmdtxt(np->nclist.body);
8534 cmdputs(";; ");
8535 }
8536 p = "esac";
8537 goto dotail2;
8538 case NTO:
8539 p = ">";
8540 goto redir;
8541 case NCLOBBER:
8542 p = ">|";
8543 goto redir;
8544 case NAPPEND:
8545 p = ">>";
8546 goto redir;
8547 case NTOFD:
8548 p = ">&";
8549 goto redir;
8550 case NFROM:
8551 p = "<";
8552 goto redir;
8553 case NFROMFD:
8554 p = "<&";
8555 goto redir;
8556 case NFROMTO:
8557 p = "<>";
8558 redir:
8559 s[0] = n->nfile.fd + '0';
8560 s[1] = '\0';
8561 cmdputs(s);
8562 cmdputs(p);
8563 if (n->type == NTOFD || n->type == NFROMFD) {
8564 s[0] = n->ndup.dupfd + '0';
8565 p = s;
8566 goto dotail2;
8567 }
8568 n = n->nfile.fname;
8569 goto donode;
8570 }
8571}
8572
8573static char *
8574commandtext(union node *n)
8575{
8576 char *name;
8577
8578 STARTSTACKSTR(cmdnextc);
8579 cmdtxt(n);
8580 name = stackblock();
8581 TRACE(("commandtext: name %p, end %p\n\t\"%s\"\n",
8582 name, cmdnextc, cmdnextc));
8583 return ckstrdup(name);
8584}
8585#endif /* JOBS */
8586
8587/*
8588 * Fork off a subshell. If we are doing job control, give the subshell its
8589 * own process group. Jp is a job structure that the job is to be added to.
8590 * N is the command that will be evaluated by the child. Both jp and n may
8591 * be NULL. The mode parameter can be one of the following:
8592 * FORK_FG - Fork off a foreground process.
8593 * FORK_BG - Fork off a background process.
8594 * FORK_NOJOB - Like FORK_FG, but don't give the process its own
8595 * process group even if job control is on.
8596 *
8597 * When job control is turned off, background processes have their standard
8598 * input redirected to /dev/null (except for the second and later processes
8599 * in a pipeline).
8600 *
8601 * Called with interrupts off.
8602 */
8603/*
8604 * Clear traps on a fork.
8605 */
8606static void
8607clear_traps(void)
8608{
8609 char **tp;
8610
8611 for (tp = trap; tp < &trap[NSIG]; tp++) {
8612 if (*tp && **tp) { /* trap not NULL or SIG_IGN */
8613 INT_OFF;
8614 free(*tp);
8615 *tp = NULL;
8616 if (tp != &trap[0])
8617 setsignal(tp - trap);
8618 INT_ON;
8619 }
8620 }
8621}
8622static void
8623forkchild(struct job *jp, union node *n, int mode)
8624{
8625 int oldlvl;
8626
8627 TRACE(("Child shell %d\n", getpid()));
8628 oldlvl = shlvl;
8629 shlvl++;
8630
8631 closescript();
8632 clear_traps();
8633#if JOBS
8634 /* do job control only in root shell */
8635 jobctl = 0;
8636 if (mode != FORK_NOJOB && jp->jobctl && !oldlvl) {
8637 pid_t pgrp;
8638
8639 if (jp->nprocs == 0)
8640 pgrp = getpid();
8641 else
8642 pgrp = jp->ps[0].pid;
8643 /* This can fail because we are doing it in the parent also */
8644 (void)setpgid(0, pgrp);
8645 if (mode == FORK_FG)
8646 xtcsetpgrp(ttyfd, pgrp);
8647 setsignal(SIGTSTP);
8648 setsignal(SIGTTOU);
8649 } else
8650#endif
8651 if (mode == FORK_BG) {
8652 ignoresig(SIGINT);
8653 ignoresig(SIGQUIT);
8654 if (jp->nprocs == 0) {
8655 close(0);
8656 if (open(bb_dev_null, O_RDONLY) != 0)
8657 ash_msg_and_raise_error("Can't open %s", bb_dev_null);
8658 }
8659 }
8660 if (!oldlvl && iflag) {
8661 setsignal(SIGINT);
8662 setsignal(SIGQUIT);
8663 setsignal(SIGTERM);
8664 }
8665 for (jp = curjob; jp; jp = jp->prev_job)
8666 freejob(jp);
8667 jobless = 0;
8668}
8669
8670static void
8671forkparent(struct job *jp, union node *n, int mode, pid_t pid)
8672{
8673 TRACE(("In parent shell: child = %d\n", pid));
8674 if (!jp) {
8675 while (jobless && dowait(DOWAIT_NORMAL, 0) > 0);
8676 jobless++;
8677 return;
8678 }
8679#if JOBS
8680 if (mode != FORK_NOJOB && jp->jobctl) {
8681 int pgrp;
8682
8683 if (jp->nprocs == 0)
8684 pgrp = pid;
8685 else
8686 pgrp = jp->ps[0].pid;
8687 /* This can fail because we are doing it in the child also */
8688 setpgid(pid, pgrp);
8689 }
8690#endif
8691 if (mode == FORK_BG) {
8692 backgndpid = pid; /* set $! */
8693 set_curjob(jp, CUR_RUNNING);
8694 }
8695 if (jp) {
8696 struct procstat *ps = &jp->ps[jp->nprocs++];
8697 ps->pid = pid;
8698 ps->status = -1;
8699 ps->cmd = nullstr;
8700#if JOBS
8701 if (jobctl && n)
8702 ps->cmd = commandtext(n);
8703#endif
8704 }
8705}
8706
8707static int
8708forkshell(struct job *jp, union node *n, int mode)
8709{
8710 int pid;
8711
8712 TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode));
8713 pid = fork();
8714 if (pid < 0) {
8715 TRACE(("Fork failed, errno=%d", errno));
8716 if (jp)
8717 freejob(jp);
8718 ash_msg_and_raise_error("Cannot fork");
8719 }
8720 if (pid == 0)
8721 forkchild(jp, n, mode);
8722 else
8723 forkparent(jp, n, mode, pid);
8724 return pid;
8725}
8726
8727/*
8728 * Wait for job to finish.
8729 *
8730 * Under job control we have the problem that while a child process is
8731 * running interrupts generated by the user are sent to the child but not
8732 * to the shell. This means that an infinite loop started by an inter-
8733 * active user may be hard to kill. With job control turned off, an
8734 * interactive user may place an interactive program inside a loop. If
8735 * the interactive program catches interrupts, the user doesn't want
8736 * these interrupts to also abort the loop. The approach we take here
8737 * is to have the shell ignore interrupt signals while waiting for a
8738 * foreground process to terminate, and then send itself an interrupt
8739 * signal if the child process was terminated by an interrupt signal.
8740 * Unfortunately, some programs want to do a bit of cleanup and then
8741 * exit on interrupt; unless these processes terminate themselves by
8742 * sending a signal to themselves (instead of calling exit) they will
8743 * confuse this approach.
8744 *
8745 * Called with interrupts off.
8746 */
8747static int
8748waitforjob(struct job *jp)
8749{
8750 int st;
8751
8752 TRACE(("waitforjob(%%%d) called\n", jobno(jp)));
8753 while (jp->state == JOBRUNNING) {
8754 dowait(DOWAIT_BLOCK, jp);
8755 }
8756 st = getstatus(jp);
8757#if JOBS
8758 if (jp->jobctl) {
8759 xtcsetpgrp(ttyfd, rootpid);
8760 /*
8761 * This is truly gross.
8762 * If we're doing job control, then we did a TIOCSPGRP which
8763 * caused us (the shell) to no longer be in the controlling
8764 * session -- so we wouldn't have seen any ^C/SIGINT. So, we
8765 * intuit from the subprocess exit status whether a SIGINT
8766 * occurred, and if so interrupt ourselves. Yuck. - mycroft
8767 */
8768 if (jp->sigint)
8769 raise(SIGINT);
8770 }
8771 if (jp->state == JOBDONE)
8772#endif
8773 freejob(jp);
8774 return st;
8775}
8776
8777/*
8778 * return 1 if there are stopped jobs, otherwise 0
8779 */
8780static int
8781stoppedjobs(void)
8782{
8783 struct job *jp;
8784 int retval;
8785
8786 retval = 0;
8787 if (job_warning)
8788 goto out;
8789 jp = curjob;
8790 if (jp && jp->state == JOBSTOPPED) {
8791 out2str("You have stopped jobs.\n");
8792 job_warning = 2;
8793 retval++;
8794 }
8795 out:
8796 return retval;
8797}
8798
8799
8800/* ============ mail.c 8809/* ============ mail.c
8801 * 8810 *
8802 * Routines to check for mail. 8811 * Routines to check for mail.
@@ -9157,22 +9166,6 @@ setcmd(int argc, char **argv)
9157 return 0; 9166 return 0;
9158} 9167}
9159 9168
9160#if ENABLE_LOCALE_SUPPORT
9161static void
9162change_lc_all(const char *value)
9163{
9164 if (value && *value != '\0')
9165 setlocale(LC_ALL, value);
9166}
9167
9168static void
9169change_lc_ctype(const char *value)
9170{
9171 if (value && *value != '\0')
9172 setlocale(LC_CTYPE, value);
9173}
9174#endif
9175
9176#if ENABLE_ASH_RANDOM_SUPPORT 9169#if ENABLE_ASH_RANDOM_SUPPORT
9177/* Roughly copied from bash.. */ 9170/* Roughly copied from bash.. */
9178static void 9171static void