misc/127370: sh -c 'exit -1' fails with "Illegal number: -1",
instead of exiting with a code of 255
Andrei Lavreniyuk
andy.lavr at reactor-xg.kiev.ua
Sun Sep 14 05:20:02 UTC 2008
>Number: 127370
>Category: misc
>Synopsis: sh -c 'exit -1' fails with "Illegal number: -1", instead of exiting with a code of 255
>Confidential: no
>Severity: non-critical
>Priority: medium
>Responsible: freebsd-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: sw-bug
>Submitter-Id: current-users
>Arrival-Date: Sun Sep 14 05:20:01 UTC 2008
>Closed-Date:
>Last-Modified:
>Originator: Andrei Lavreniyuk
>Release: 7.1-PRERELEASE
>Organization:
Technica-03, Inc.
>Environment:
FreeBSD datacenter.technica-03.local 7.1-PRERELEASE FreeBSD 7.1-PRERELEASE #0: Fri Sep 12 21:28:43 UTC 2008 root at datacenter.technica-03.local:/usr/obj/usr/src/sys/SMP-DATACENTER i386
>Description:
(c) Garrett Cooper (misc_124748)
----------------------------------------
Bourne shell (/bin/sh), as it stands, doesn't parse numbers properly, even though bash does:
[gcooper at optimus /devel/ncvs/src/bin/sh]$ sh -c 'exit -1'
exit: Illegal number: -1
[gcooper at optimus /devel/ncvs/src/bin/sh]$ sh -c 'exit +1'
exit: Illegal number: +1
These are valid numbers though, which are merely red herrings; the patch attached does fix this behavior though, according to the following gamut of tests:
[gcooper at optimus /devel/ncvs/src/bin/sh]$ cat number_test.sh
#!/bin/sh
for shell in sh $@; do
for i in -1 1 +1; do
echo "$shell -c \"exit $i\""
$shell -c "exit $i"; echo $?
done;
done
# End of test
[gcooper at optimus /devel/ncvs/src/bin/sh]$ ./number_test.sh bash ./sh
sh -c "exit -1"
exit: Illegal number: -1
2
sh -c "exit 1"
1
sh -c "exit +1"
exit: Illegal number: +1
2
bash -c "exit -1"
255
bash -c "exit 1"
1
bash -c "exit +1"
1
./sh -c "exit -1"
255
./sh -c "exit 1"
1
./sh -c "exit +1"
1
>How-To-Repeat:
(c) Garrett Cooper (misc_124748)
----------------------
/bin/sh -c "exit -1"
/bin/sh -c "exit +1"
>Fix:
(c) Garrett Cooper (misc_124748)
-----------------
Patch attached (also fixes histcmd.c and trap.c -- strange thing is that I can't seem to test that builtin cmd), and maintains proper compatibility with builtin jobs:
[gcooper at optimus /devel/ncvs/src/bin/sh]$ sh -c 'builtin histcmd'
histcmd: not found
Patch attached with submission follows:
Index: exec.c
===================================================================
RCS file: /home/ncvs/src/bin/sh/exec.c,v
retrieving revision 1.31
diff -r1.31 exec.c
40a41
> #include <string.h>
361c362
< if (prefix("builtin", pathopt)) {
---
> if (strncmp(BUILTIN, pathopt, strlen(BUILTIN)) == 0) {
Index: histedit.c
===================================================================
RCS file: /home/ncvs/src/bin/sh/histedit.c,v
retrieving revision 1.29
diff -r1.29 histedit.c
425,426d424
< if (*s == '-')
< s++;
Index: jobs.c
===================================================================
RCS file: /home/ncvs/src/bin/sh/jobs.c,v
retrieving revision 1.72
diff -r1.72 jobs.c
534c534
< return (jp);
---
> return jp;
540c540,544
< jobno = number(name + 1);
---
> /*
> * Don't use number() here. This breaks existing
> * jobs(1) compatibility.
> */
> jobno = atoi(name + 1);
560c564
< if (found)
---
> if (found != NULL)
571,572c575,576
< && prefix(name + 1, jp->ps[0].cmd)) {
< if (found)
---
> && strncmp(name+1, jp->ps[0].cmd, strlen(name+1))) {
> if (found != NULL)
577,578c581,582
< if (found)
< return found;
---
> if (found != NULL)
> return (found);
581c585,586
< pid = (pid_t)number(name);
---
> /* no need to run is_number() again with number() */
> pid = (pid_t)atoi(name);
Index: main.h
===================================================================
RCS file: /home/ncvs/src/bin/sh/main.h,v
retrieving revision 1.8
diff -r1.8 main.h
38a39,40
> #define BUILTIN "builtin"
>
Index: mystring.c
===================================================================
RCS file: /home/ncvs/src/bin/sh/mystring.c,v
retrieving revision 1.13
diff -r1.13 mystring.c
56a57,59
> #if DEBUG
> #include <stdio.h>
> #endif
123a127,135
> /* Is this the first index? */
> int iter = 0;
>
> #if DEBUG
> #define PRINT_DEBUG fprintf(stderr, "%d: %c\n", iter, *p)
> #else
> #define PRINT_DEBUG
> #endif
>
125c137,154
< if (! is_digit(*p))
---
> /*
> * Account for signs in front of numbers.
> */
>
> /*
> * XXX: does POSIX bourne shell allow for '+' prefixed
> * numbers?
> */
>
> /*
> * The string defined by *p isn't a number, unless:
> * 1. It's a digit.
> * 2. The 0'th index is either a + or -.
> */
> if (!(is_digit(*p) ||
> (iter == 0 && (*p == '-' || *p == '+')))
> ) {
> PRINT_DEBUG;
126a156,163
> }
>
> PRINT_DEBUG;
>
> #undef PRINT_DEBUG
>
> iter++;
>
------------------------------
(c) Garrett Cooper (misc_124748)
>Release-Note:
>Audit-Trail:
>Unformatted:
More information about the freebsd-bugs
mailing list