Bug 571

Summary: Fix attached for Job Control bug in ASH shell.
Product: Busybox Reporter: Oliver Mattos <omattos>
Component: OtherAssignee: unassigned
Status: RESOLVED FIXED    
Severity: normal CC: busybox-cvs, omattos
Priority: P3    
Version: unspecified   
Target Milestone: ---   
Hardware: PC   
OS: Windows   
Host: Target:
Build: busybox 1.13.4-latest

Description Oliver Mattos 2009-08-15 19:08:17 UTC
Job control in ASH is broken.

Test script:
# sleep 20 &
# jobs %sle

Expected output:
# sleep 20 &
# jobs %sle
[1] + Running      sleep 20
# _

Actual Output:
# sleep 20 &
# jobs %sle
-sh: jobs: %sle: ambiguous
# _

Cause:
in busybox/shell/ash.c:getjob:

        found = 0;
        while (1) {
                if (!jp)
                        goto err;
                if (match(jp->ps[0].cmd, p)) {
                        if (found)
                                goto err;
                        found = jp;
                        err_msg = "%s: ambiguous";
                }
                jp = jp->prev_job;
        }

Fix:
The above code can NEVER work, because there is no exit from the while loop even if the correct job is found.  It should be replaced with this:

        found = 0;
        while (jp) {
                if (match(jp->ps[0].cmd, p)) {
                        if (found)
                                goto err;
                        found = jp;
                        err_msg = "%s: ambiguous";
                }
                jp = jp->prev_job;
        }
        if (!found)
                goto err;

Note that it appears err_msg isn't set before going to err, but it is set at the start of the function.

I'm not a regular around here, so I'll leave this here for someone with commit access to make this change.
Comment 1 Oliver Mattos 2009-08-15 22:43:32 UTC
Sorry - just read through this again and realised I was one line short.  The working code is:

         found = 0;
         while (jp) {
                 if (match(jp->ps[0].cmd, p)) {
                         if (found)
                                 goto err;
                         found = jp;
                         err_msg = "%s: ambiguous";
                 }
                 jp = jp->prev_job;
         }
         if (!found)
                 goto err;
         jp=found;


Comment 2 Denys Vlasenko 2009-08-17 00:12:38 UTC
Applied to git. Thanks!